diff --git a/instruments/AD_utilites.py b/instruments/AD_utilites.py index 684736bc9044b16e98f7fdbf4c79350cc8f272dd..19de0238d000b53210e7f0264f01da7dc3c54ec9 100644 --- a/instruments/AD_utilites.py +++ b/instruments/AD_utilites.py @@ -14,8 +14,8 @@ from time import sleep from epics import caget, caput from .IEX_endstations import * -from files_and_folders import get_next_fileNumber -from scanRecord import * +from .files_and_folders import get_next_fileNumber + def AD_CurrentDirectory(ADplugin): """ @@ -341,204 +341,7 @@ def AD_OverLayCenter_get(AD,OverLay=1,Num=1): print('x = '+str(caget(AD+":Over"+str(OverLay)+":"+str(Num)+":CenterX"))) print('y = '+str(caget(AD+":Over"+str(OverLay)+":"+str(Num)+":CenterY"))) -def Cam_ScanSetup(mda,scanDIM,camNUM): #individual files saving - pvCam="29id_ps"+str(camNUM)+":" - pvIOC=mda.ioc - #beforscan - Cam_SaveStrSeq(camNUM) - caput(pvIOC+"scan"+str(scanDIM)+".BSPV",pvIOC+"userStringSeq2.PROC") - #scan record (filename and trigger) - nextfile=str(caget(pvIOC+"saveData_baseName"))+str(caget(pvIOC+"saveData_scanNumber")) - filepath=caget(pvIOC+"saveData_fileSystem") - filepath="/net"+filepath[1:len(filepath)]+"/tif" - caput(pvCam+"TIFF1:FilePath",filepath) - caput(pvCam+"TIFF1:FileName",nextfile) - caput(pvCam+"TIFF1:FileWriteMode","Single") - caput(pvIOC+"scan1.T2PV",pvCam+"cam1:Acquire") - #afterscan - Cam_FreeStrSeq(camNUM) - caput(pvIOC+"scan"+str(scanDIM)+".ASPV",pvIOC+"userStringSeq1.PROC") - caput(pvIOC+"scan1.ASCD",1) - print("DON'T FORGET TO CLEAR SCAN RECORD AT THE END OF THE SCRIPT!!!!! ") - print("Use Script: Cam_ScanClear(scanIOC,scanDIM)") - - - -def Cam_FreeRun(camNUM): - camNUM=str(camNUM) - pv="29id_ps"+camNUM+":" - caput(pv+"TIFF1:AutoSave",0) - caput(pv+"TIFF1:EnableCallbacks",0) - sleep(0.5) - caput(pv+"cam1:ImageMode",2) - caput(pv+"cam1:Acquire",1) - caput(pv+"cam1:AcquireTime",0.015) - caput(pv+"cam1:AcquirePeriod",0.030) - print("Cam"+str(camNUM)+": Free run mode") - - - - - -def Cam_SaveMode(camNUM): - camNUM=str(camNUM) - pv="29id_ps"+camNUM+":" - caput(pv+"cam1:Acquire",0) - sleep(0.5) - caput(pv+"cam1:ImageMode",0) - caput(pv+"TIFF1:AutoSave",1) - caput(pv+"TIFF1:EnableCallbacks",1) - caput(pv+"TIFF1:FileNumber",1) - caput(pv+"cam1:AcquireTime",0.015) - caput(pv+"cam1:AcquirePeriod",0.030) - print("Cam"+str(camNUM)+": Saving mode") - -def Cam_Start(camNUM): - Cam_FreeRun(camNUM) - -def Cam_Stop(camNUM): - camNUM=str(camNUM) - pv="29id_ps"+camNUM+":" - caput(pv+"cam1:Acquire",0) - - - -def Cam_ROI_SetUp(xstart,ystart,xsize,ysize,camNUM,roiNUM=1,binX=1,binY=1): - pv="29id_ps"+str(camNUM)+":ROI"+str(roiNUM)+':' - caput(pv+'MinX',xstart) - caput(pv+'MinY',ystart) - caput(pv+'SizeX',xsize) - caput(pv+'SizeY',ysize) - caput(pv+'BinX',binX) - caput(pv+'BinY',binY) - caput(pv+'EnableCallbacks','Enable') - print(('ROI'+str(roiNUM)+' - '+caget(pv+'EnableCallbacks_RBV',as_string=True))) - -def Cam_ROI_Stats(xstart,ystart,xsize,ysize,camNUM,roiNUM=1,binX=1,binY=1): - pv="29id_ps"+str(camNUM)+":Stats1:" - Cam_ROI_SetUp(xstart,ystart,xsize,ysize,camNUM,roiNUM,binX,binY) - caput(pv+'EnableCallbacks','Enable') - roi=caget(pv+'NDArrayPort_RBV',as_string=True) - print((roi+' Stats => '+pv+'Total_RBV')) - print('To set-up as detector use:') - print('Cam_ROI_Det(detNUM,scanIOC,camNUM='+str(camNUM)+',roiNUM='+str(roiNUM)+')') - -def Cam_ROI_Det(detNUM,scanIOC,camNUM,roiNUM,scanDIM=1): - pvdet='29id'+scanIOC+':scan'+str(scanDIM)+'.D'+str(detNUM)+'PV' - pvroi="29id_ps"+str(camNUM)+":Stats1:Total_RBV" - caput(pvdet,pvroi) - print('ROI stats set up as detector D'+str(detNUM)+' in '+scanIOC+' scan'+str(scanDIM)) - -### Scan Record Set-Up: - -def Scan_Cam_Go(mda,VAL,RBV,scanDIM,start,stop,step,camNUM): - mda.fillin(scanDIM,VAL,RBV,start,stop,step) - Cam_ScanSetup(scanDIM,camNUM) - - caput("29id"+scanIOC+":scan"+str(scanDIM)+".PASM","STAY") - # Scan_Go() without Before_After_Scan() - BL_mode=BL_Mode_Read()[0] - if BL_mode != 2: - Check_MainShutter() - FileName = caget("29id"+scanIOC+":saveData_baseName",as_string=True) - FileNum = caget("29id"+scanIOC+":saveData_scanNumber") - print(FileName+": #"+str(FileNum)+" started at ", dateandtime()) - caput("29id"+scanIOC+":scan"+str(scanDIM)+".EXSC",1,wait=True,timeout=900000) #pushes scan button - print(FileName+": #"+str(FileNum)+" finished at ", dateandtime()) - - Cam_ScanClear(scanIOC,scanDIM) - caput("29id"+scanIOC+":scan"+str(scanDIM)+".PASM","PRIOR POS") - -def Scan_Cam_Pos2_Go(VAL1,RBV1,VAL2,RBV2,scanDIM,start1,stop1,step1,start2,stop2,camNUM): - scanIOC=BL_ioc() - pvCam="29id_ps"+str(camNUM)+":" - Cam_ScanSetup(scanDIM,camNUM) - Scan_FillIn(VAL1,RBV1,scanIOC,scanDIM,start1,stop1,step1) - Scan_FillIn_Pos2(VAL2,RBV2,scanIOC,scanDIM,start2,stop2) - caput("29id"+scanIOC+":scan"+str(scanDIM)+".PASM","STAY") - mda.goScan_Go(scanIOC,scanDIM=1 ) - Cam_ScanClear(scanIOC,scanDIM) - caput("29id"+scanIOC+":scan"+str(scanDIM)+".PASM","PRIOR POS") - -def Cam_ScanClear(scanIOC,scanDIM): - caput("29id"+scanIOC+":scan"+str(scanDIM)+".BSPV","") - caput("29id"+scanIOC+":scan"+str(scanDIM)+".ASPV","") - caput("29id"+scanIOC+":scan"+str(scanDIM)+".T2PV","") - caput("29id"+scanIOC+":scan"+str(scanDIM)+".DDLY",0.5) - #print "Scan Record cleared from Camera Settings" - - - -### Image Acquisition: - -def TakeImageSetFolder(camNUM,NewFolder=""): - scanIOC=BL.ioc - pvCam="29id_ps"+str(camNUM)+":" - pvIOC="29id"+scanIOC+":" - #beforscan - Cam_SaveMode(camNUM) - #FilePath - filepath=caget(pvIOC+"saveData_fileSystem")+"/tif" - filepath="/net"+filepath[1:len(filepath)]+"/"+NewFolder - caput(pvCam+"TIFF1:FilePath",filepath) - print("WARNING: Make sure NewFolder exists !!!") - -def TakeImageSetFileNum(camNUM,n): - scanIOC=BL.mda.ioc - pvCam="29id_ps"+str(camNUM)+":" - pvIOC="29id"+scanIOC+":" - #beforscan -# Cam_SaveMode(camNUM) - #Filename - if n<10: - nextfile="29id"+scanIOC+"_000"+str(n) - elif n<100: - nextfile="29id"+scanIOC+"_00"+str(n) - elif n<1000: - nextfile="29id"+scanIOC+"_0"+str(n) - elif n<10000: - nextfile="29id"+scanIOC+"_"+str(n) - caput(pvCam+"TIFF1:FileName",nextfile) - caput(pvCam+"TIFF1:AutoIncrement",1) - caput(pvCam+"TIFF1:FileNumber",2) - -def TakeImageSetup(camNUM): - scanIOC=BL.mda.ioc - pvCam="29id_ps"+str(camNUM)+":" - pvIOC="29id"+scanIOC+":" - #beforscan - Cam_SaveMode(camNUM) - #Filename - nextfile=str(caget(pvIOC+"saveData_baseName"))+str(caget(pvIOC+"saveData_scanNumber")-1) - filepath=caget(pvIOC+"saveData_fileSystem")+"/tif" - if scanIOC == "Test": - filepath="/"+filepath[1:len(filepath)] # for 29idTest - else: - filepath="/net"+filepath[1:len(filepath)] # for 29idb/c/d - - caput(pvCam+"TIFF1:FilePath",filepath) - caput(pvCam+"TIFF1:FileName",nextfile) - #afterscan - -def TakeImage(camNUM,AcqTime): - AcqPeriode=AcqTime+0.040 - pvCam="29id_ps"+str(camNUM)+":" - caput(pvCam+"cam1:AcquireTime",AcqTime) - caput(pvCam+"cam1:AcquirePeriod",AcqPeriode) - sleep(1) - caput(pvCam+"cam1:Acquire",1,wait=True,timeout=500) - sleep(1) - TiffNum =caget(pvCam+"TIFF1:FileNumber_RBV")-1 - FileName= caget(pvCam+"TIFF1:FileName_RBV",as_string=True) - print("\n"+FileName+": #"+str(TiffNum)+" started at ", dateandtime()) - print("\n================================================\n") - - - - - - diff --git a/instruments/ARPES.py b/instruments/ARPES.py index 1a60b81c8e13caf4c6df8dd055a54cee39a8a329..e75349413c9c5f4aa0ab6077663715fc0c1fe7f1 100644 --- a/instruments/ARPES.py +++ b/instruments/ARPES.py @@ -3,27 +3,29 @@ from time import sleep from epics import caget,caput,PV from .IEX_endstations import * +from .staff import staff_detector_dictionary from .files_and_folders import check_run,make_user_folders,folder_mda -from .userCalcs import userStringSeq_clear, userStringSeq_pvs +from .staff import staff_detector_dictionary from .logfile import logfile_name_set,logfile_header -from .utilities import * + from .conversions_constants import * +from .utilities import * +from .userCalcs import userStringSeq_clear, userStringSeq_pvs + from .scanRecord import * +from .Motors import * +from .xrays import * from .current_amplifiers import * -from .slits import slit3C_get from .gate_valves import valve_close, branch_valves from .shutters import branch_shutter_close -from .xrays import * -from .Lakeshore_335 import Lakeshore_reset -from .electron_analyzer import folders_EA -from .Motors import * - +from .slits import slit3C_get -EA_pv="29idcScienta:HV:KineticEnergy.VAL" +from .Lakeshore_335 import Lakeshore_reset +from .electron_analyzer import folders_EA,EA ############################################################################# -def __main__(set_folders=False,reset=False,**kwargs): +def ARPES_init(set_folders=False,reset=False,**kwargs): """ kwargs: set_folders: sets the mda and EA folders; default => False @@ -34,16 +36,21 @@ def __main__(set_folders=False,reset=False,**kwargs): kwargs.setdefault('BL_mode','user') #scan - mda_scanRecord = ScanRecord(kwargs['scan_ioc'],ARPES_detector_dictionary,ARPES_trigger_dictionary,ARPES_scan_before_sequence,ARPES_scan_after_sequence,mda) + if kwargs['BL_mode']=='staff': + detector_dictionary = staff_detector_dictionary() + else: + detector_dictionary = ARPES_detector_dictionary() + mda_scanRecord = ScanRecord(kwargs['scan_ioc'],detector_dictionary, + ARPES_trigger_dictionary(),ARPES_scan_before_sequence(),ARPES_scan_after_sequence()) #endstation global BL BL=Endstation('ARPES',kwargs['scan_ioc'],kwargs['xrays'],kwargs['BL_mode'],mda_scanRecord) #EA - global EA - pv=PV(EA_pv);sleep(0.1) - if not pv.connected: + try: + EA.get() + except: print("\n\n NOTE: Scienta IOC is not running - start IOC and %run Macros_29id/ScanFunctions_EA.py\n\n") #global detectors @@ -54,8 +61,11 @@ def __main__(set_folders=False,reset=False,**kwargs): #setting folders if 'set_folders': + if BL.mode == 'staff': + user_name = 'staff' + else: user_name = input('user name: ') - folders_ARPES(user_name,**kwargs) + folders_ARPES(user_name,**kwargs) #resetting if 'reset': @@ -170,10 +180,8 @@ def folders_ARPES(user_name,**kwargs): #Set up Scienta folders: try: - pv=PV(EA_pv); sleep(0.1) - if pv.connected: - userPath = "/net/s29data/export/data_29id"+BL.folder+"/"+run+"/"+user_name+"/" - folders_EA(userPath,filePrefix="EA") + userPath = "/net/s29data/export/data_29id"+BL.folder+"/"+run+"/"+user_name+"/" + folders_EA(userPath,filePrefix="EA") except: print_warning_message("EA ioc is not running, cannot set folder") diff --git a/instruments/IEX_endstations.py b/instruments/IEX_endstations.py index d6d823ce56edf9ccf32e800012f0ab2afcbcbf92..5c3fd1895611de62aa2c47eb62225feae413d52e 100644 --- a/instruments/IEX_endstations.py +++ b/instruments/IEX_endstations.py @@ -73,12 +73,6 @@ class Endstation: self.ioc = scan_ioc self.mda = mda_scanRecord - global mda - mda = mda_scanRecord - - global Motors - - def set_logfile_path(): """ diff --git a/instruments/Kappa.py b/instruments/Kappa.py index 92a8d4af274aa01a18664fe1045314bc7bd0cc18..d7809497454d44b667588f60cdeebcf88a145485 100644 --- a/instruments/Kappa.py +++ b/instruments/Kappa.py @@ -3,37 +3,52 @@ from time import sleep from math import floor from epics import caget, caput,PV +from .IEX_endstations import * +from .staff import staff_detector_dictionary from .files_and_folders import check_run,make_user_folders,folder_mda -from .userCalcs import userStringSeq_clear, userStringSeq_pvs +from .staff import staff_detector_dictionary from .logfile import logfile_name_set,logfile_header -from .utilities import * + from .conversions_constants import * +from .utilities import * +from .userCalcs import userStringSeq_clear, userStringSeq_pvs + from .scanRecord import * +from .Motors import * +from .xrays import * from .current_amplifiers import * -from .slits import slit3C_get from .gate_valves import valve_close, branch_valves from .shutters import branch_shutter_close -from .IEX_endstations import Endstation -from .xrays import * +from .slits import slit3D_get + from .Kappa_det import * from .spec_stuff import folders_spec -from .Motors import * + ############################################################################# -def __main__(set_folders=False,reset=False,**kwargs): +def Kappa_init(set_folders=False,reset=False,**kwargs): """ - kwargs: - set_folders: sets the mda and EA folders; default => False - xrays: sets global variable; default => True + + 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... """ kwargs.setdefault('scan_ioc','29idKappa:') kwargs.setdefault('xrays',True) kwargs.setdefault('BL_mode','user') #scan - mda_scanRecord = ScanRecord(kwargs['scan_ioc'],Kappa_detector_dictionary,Kappa_trigger_dictionary,Kappa_scan_before_sequence,Kappa_scan_after_sequence,mda_scanRecord) + if kwargs['BL_mode']=='staff': + detector_dictionary = staff_detector_dictionary() + else: + detector_dictionary = Kappa_detector_dictionary() + + mda_scanRecord = ScanRecord(kwargs['scan_ioc'],detector_dictionary, + Kappa_trigger_dictionary(),Kappa_scan_before_sequence(),Kappa_scan_after_sequence()) #endstation global BL @@ -52,7 +67,10 @@ def __main__(set_folders=False,reset=False,**kwargs): #setting folders if 'set_folders': - user_name = input('user name: ') + if BL.mode == 'staff': + user_name = 'staff' + else: + user_name = input('user name: ') folders_Kappa(user_name,**kwargs) #resetting @@ -643,13 +661,13 @@ def Kappa_th2th_scan_sensitivity(th_table,gain_num_table,gain_unit_table,detecto print("\nDon't forget to clear extra positionners at the end of the scan if you were to abort the script using the function:") print(" Clear_Scan_Positioners('Kappa',1)") - Kappa_cts(kwargs['cts'],verbose=False) + scaler_cts(kwargs['cts'],verbose=False) if kwargs['execute']: mda.go(**kwargs) #clean up after scan mda.table_reset_after(**kwargs) - Kappa_cts(verbose=False) + scaler_cts(verbose=False) def Kappa_scan_th2th(tth_start,tth_stop,tth_step,th_offset,**kwargs): """ @@ -676,17 +694,16 @@ def Kappa_scan_th2th(tth_start,tth_stop,tth_step,th_offset,**kwargs): tth_val,tth_rbv,tth_spmg,tth_pv = Kappa_motor_dictionary['tth'] kwargs.update("positioner_num",1) - BL.mda.fillin(kth_val,kth_rbv,kth_val,kth_rbv,**kwargs) - + BL.mda.fillin(tth_val,tth_rbv,tth_start,tth_stop,tth_step,**kwargs) kwargs.update("positioner_num",2) - BL.mda.fillin(tth_val,tth_rbv,tth_val,tth_rbv,**kwargs) + BL.mda.fillin(th_val,th_rbv,th_start,th_stop,th_step,**kwargs) - Kappa_cts(kwargs['cts'],verbose=False) + scaler_cts(kwargs['cts'],verbose=False) if kwargs['execute']: BL.mda.go(**kwargs) #clean up after scan - Kappa_cts(verbose=False) + scaler_cts(verbose=False) def scan_th2th_table(tth_table,th0,**kwargs): @@ -726,13 +743,13 @@ def scan_th2th_table(tth_table,th0,**kwargs): BL.mda.positioner_after_scan(after="STAY") - Kappa_cts(kwargs['cts'],verbose=False,**kwargs) + scaler_cts(kwargs['cts'],verbose=False,**kwargs) if kwargs['execute']: BL.mda.go(**kwargs) #clean up after scan BL.mda.table_reset_after() - Kappa_cts(verbose=False) + scaler_cts(verbose=False) BL.mda.positioner_after_scan(after="PRIOR POS",**kwargs) diff --git a/instruments/Kappa_Euler.py b/instruments/Kappa_Euler.py index 84bf299ebf20ded4f024f3a2fa4aad71f63a3da5..cd2dbfba809e9dd872a3dbbd3429210cf57ff883 100644 --- a/instruments/Kappa_Euler.py +++ b/instruments/Kappa_Euler.py @@ -1,6 +1,9 @@ +import numpy as np from epics import caget, caput -from userCalcs import userCalcOut_clear +from .userCalcs import userCalcOut_clear +from .IEX_endstations import mda +from .userCalcs import userCalcOut_clear #### Obsolete? @@ -16,7 +19,7 @@ def Bragg_Index_CalcOut(d,eV,th): caput(userCalcOut_pv+".A",d) caput(userCalcOut_pv+".B",th) caput(userCalcOut_pv+".C",eV) - caput(userCalcOut_pv+".D",pi) + caput(userCalcOut_pv+".D",np.pi) caput(userCalcOut_pv+".E",f) caput(userCalcOut_pv+".CALC$","SIN(B*D/"+str(180)+")*"+str(2)+"*A*C/E") @@ -84,18 +87,17 @@ def EtoK_kth_CalcOut(): def EtoK_kap_CalcOut(): n=5 - scanIOC='Kappa' - ClearCalcOut(scanIOC,n) - pvcal="29id"+scanIOC+":userCalcOut"+str(n) - caput(pvcal+".DESC","EtoK_kap") - caput(pvcal+".INPA","29idKappa:userCalcOut1.VAL CP NMS") #A=th - caput(pvcal+".INPB","29idKappa:userCalcOut2.VAL CP NMS") #B=chi - caput(pvcal+".INPC","29idKappa:userCalcOut3.VAL CP NMS") #C=phi - caput(pvcal+".D",3.141592653589793) - caput(pvcal+".E",180) - caput(pvcal+".F",50) - caput(pvcal+".CALC$","((2*ASIN(SIN(B*D/E/2.0) / SIN(F*D/E))))*E/D") - caput(pvcal+".DOPT",0) # Use CAL + userCalcOut_pv = userCalcOut_clear(mda,n) + + caput(userCalcOut_pv+".DESC","EtoK_kap") + caput(userCalcOut_pv+".INPA","29idKappa:userCalcOut1.VAL CP NMS") #A=th + caput(userCalcOut_pv+".INPB","29idKappa:userCalcOut2.VAL CP NMS") #B=chi + caput(userCalcOut_pv+".INPC","29idKappa:userCalcOut3.VAL CP NMS") #C=phi + caput(userCalcOut_pv+".D",3.141592653589793) + caput(userCalcOut_pv+".E",180) + caput(userCalcOut_pv+".F",50) + caput(userCalcOut_pv+".CALC$","((2*ASIN(SIN(B*D/E/2.0) / SIN(F*D/E))))*E/D") + caput(userCalcOut_pv+".DOPT",0) # Use CAL def EtoK_kphi_CalcOut(): n=6 diff --git a/instruments/Kappa_det.py b/instruments/Kappa_det.py index 977c1d54f2473961d5d505f539e5685633270edf..14b2f04beb839662c0cc883b804fbd1656527838 100644 --- a/instruments/Kappa_det.py +++ b/instruments/Kappa_det.py @@ -3,9 +3,13 @@ from epics import caget, caput from .IEX_endstations import Motors + ############################################################################################################## ################################ Kappa detector class ############################## ############################################################################################################## +det_set_pv = '29idKappa:det:set' +det_list = 'd3', 'd4', 'mcp', 'apd', 'yag' + class Kappa_Detector: """ class for Kappa detector diff --git a/instruments/Motors.py b/instruments/Motors.py index 54257bedd8e2130c8a61375dacbbc54225280023..24085c5a29908b4789a68ab03e4a8979504fd9ac 100644 --- a/instruments/Motors.py +++ b/instruments/Motors.py @@ -115,7 +115,7 @@ class Motors: position_list.append(self.get(motor,verbose=False)) return position_list - def mvsample(self,position_list): + def mvsample(self,position_list,verbose=True): """ moves the sample to the position sepcified by position_list position_list = ['description',x,y,z,th,chi,phi] @@ -170,10 +170,10 @@ class Motors: abs_stop = stop self._scalar_cts(kwargs['cts'],verbose=True,**kwargs) - mda.fillin(val_pv,rbv_pv,abs_start,abs_stop,step,**kwargs) + BL.mda.fillin(val_pv,rbv_pv,abs_start,abs_stop,step,**kwargs) if kwargs['execute']: - mda.go(**kwargs) + BL.mda.go(**kwargs) def scan_2D(self,inner_loop_list,outer_loop_list,**kwargs): @@ -221,11 +221,11 @@ class Motors: outer_loop_list[3]=round(current_value1+outer_loop_list[3],3) scalar_cts(kwargs['cts'],verbose=True,**kwargs) - mda.fillin_2D(inner_loop_list,outer_loop_list, + BL.mda.fillin_2D(inner_loop_list,outer_loop_list, outer_scan_dim=kwargs['outer_scan_dim'],**kwargs) if kwargs['execute']: - mda.go(**kwargs) + BL.mda.go(**kwargs) diff --git a/instruments/VLS_PGM.py b/instruments/VLS_PGM.py index 49f0cd87a1900133d5dce7b5104a5eb605a6ebe0..4ca6dd8164e2089ba1132de1861e722a0674ec6e 100644 --- a/instruments/VLS_PGM.py +++ b/instruments/VLS_PGM.py @@ -74,6 +74,50 @@ def mono_get_all(verbose=False): print(" grating : "+vals['grating']," mirror : "+vals['mirror']) return vals +def mono_grating_num(): + """returns the current grating num""" + return caget('29idmonoGRT_TYPE_MON') + +def mono_mirror_num(): + """returns the current mirror num""" + return caget('29idmonoMIR_TYPE_MON') + +def mono_pvs(grt_num=None,mir_num=None): + """ + returns a dictionary with all the mono pvs + """ + if grt_num is None: + grt_num = mono_grating_num() + if mir_num is None: + mir_num = mono_mirror_num() + + ext=mono_extensions() + + d={ + 'energy':"29idmono:ENERGY_MON", + 'energy_sp':"29idmono:ENERGY_SP", + 'grt_density':"29idmono:GRT_DENSITY", + 'grt_offset':'29idmonoGRT:P_OFFSETS.'+ext['grt_num'], + 'grt_b2':'29idmonoGRT:B2_CALC.'+ext['grt_num'], + 'grt_pos':'29idmonoGRT:X_DEF_POS.'+ext['grt_num'], + 'grt_LD':'29idmonoGRT:TYPE_CALC.'+ext['grt_num'], + 'grt_tun0':'29idmonoGRT:TUN0_CALC.'+ext['grt_num'], + 'grt_tun1':'29idmonoGRT:TUN1_CALC.'+ext['grt_num'], + 'grt_tun2':'29idmonoGRT:TUN2_CALC.'+ext['grt_num'], + 'grt_tun3':'29idmonoGRT:TUN3_CALC.'+ext['grt_num'], + 'grt_type_sp':"29idmonoGRT_TYPE_SP", + 'grt_move':"29idb:'gr:move", + 'grt_P_status':"29idmonoGRT:P_AXIS_STS", + 'mir_P_status':"29idmonoMIR:P_AXIS_STS", + 'grt_X_status':"29idmonoGRT:X_AXIS_STS", + 'mir_X_status':"29idmonoMIR:X_AXIS_STS", + 'mir_offset':'29idmonoMIR:P_OFFSETS.'+ext['mir_num'], + 'mir_pos':'29idmonoMIR:X_DEF_POS.'+ext['mir_num'], + 'cff':'29idmono:CC_MON', + 'arm':'29idmono:PARAMETER.G' + + } + def mono_get_all_extended(verbose=False): """ gets the mono parameters for the current grating and mirror @@ -81,38 +125,38 @@ def mono_get_all_extended(verbose=False): Previously: Mono_Optics """ + grt_num = mono_grating_num() + mir_num = mono_mirror_num() + grt_names = mono_grating_names() + mir_names = mono_mirror_names() - GRT_state=caget('29idmonoGRT_TYPE_MON') - MIR_state=caget('29idmonoMIR_TYPE_MON') - GRT_names = mono_grating_names() - MIR_names = mono_mirror_names() - - ext=["C","D","E","F","G","H","I","J","K","L"] + ext=mono_extensions() + pvs = mono_pvs(grt_num=None,mir_num=None) vals={ - 'grating_state':GRT_state, - 'mirror_state':MIR_state, - 'GRT':GRT_names[GRT_state], - 'MIR':MIR_names[MIR_state], - 'ENERGY_MON':caget("29idmono:ENERGY_MON"), - 'ENERGY_SP':caget("29idmono:ENERGY_SP"), - 'GRT_DENSITY':caget("29idmono:GRT_DENSITY"), - 'GRT_Offset':caget('29idmonoGRT:P_OFFSETS.'+ext[GRT_state]), - 'GRT_b2':caget('29idmonoGRT:B2_CALC.'+ext[GRT_state]), - 'GRT_Tx':caget('29idmonoGRT:X_DEF_POS.'+ext[GRT_state]), - 'GRT_LD':caget('29idmonoGRT:TYPE_CALC.'+ext[GRT_state]), - 'TUN0':caget('29idmonoGRT:TUN0_CALC.'+ext[GRT_state]), - 'TUN1':caget('29idmonoGRT:TUN1_CALC.'+ext[GRT_state]), - 'TUN2':caget('29idmonoGRT:TUN2_CALC.'+ext[GRT_state]), - 'TUN3':caget('29idmonoGRT:TUN3_CALC.'+ext[GRT_state]), - 'GRT_P_status':caget("29idmonoGRT:P_AXIS_STS"), - 'MIR_P_status':caget("29idmonoMIR:P_AXIS_STS"), - 'GRT_X_status':caget("29idmonoGRT:X_AXIS_STS"), - 'MIR_X_status':caget("29idmonoMIR:X_AXIS_STS"), - 'MIR_Offset':caget('29idmonoMIR:P_OFFSETS.'+ext[MIR_state]), - 'MIR_Tx':caget('29idmonoMIR:X_DEF_POS.'+ext[MIR_state]), + 'grt_num':grt_num, + 'mir_num':mir_num, + 'grt':grt_names[grt_num], + 'mir':mir_names[mir_num], + 'energy':caget(pvs['energy']), + 'energy_sp':caget(pvs['energy_sp']), + 'grt_density':caget(pvs['energy_sp']), + 'grt_offset':caget(pvs['grt_offset']), + 'grt_b2':caget(pvs['grt_offset']), + 'grt_pos':caget(pvs['grt_pos']), + 'grt_LD':caget(pvs['grt_LD']), + 'grt_tun0':caget(pvs['grt_tun0']), + 'grt_tun1':caget(pvs['grt_tun1']), + 'grt_tun2':caget(pvs['grt_tun2']), + 'grt_tun3':caget(pvs['grt_tun3']), + 'grt_P_status':caget(pvs['grt_P_status']), + 'mir_P_status':caget(pvs['mir_P_status']), + 'grt_X_status':caget(pvs['grt_X_status']), + 'mir_X_status':caget(pvs['mir_X_status']), + 'mir_offset':caget(pvs['mir_offset']), + 'mir_pos':caget(pvs['mir_pos']), 'CFF':caget('29idmono:CC_MON'), - 'ARM':caget('29idmono:PARAMETER.G') + 'arm':caget('29idmono:PARAMETER.G') } if verbose: @@ -125,14 +169,19 @@ def mono_grating_get(): """ returns the grating density and the string name for the grating """ - return mono_get_all_extended()['GRT'] + return mono_get_all_extended()['grt'] def mono_energy_get(): """ returns the grating density and the string name for the grating """ - return mono_get_all_extended()['ENERGY_MON'] + return mono_get_all_extended()['energy'] +def mono_grating_density_get(): + """ + returns the grating density and the string name for the grating + """ + return mono_get_all_extended()['grt_density'] def mono_energy_set(hv_eV,verbose=True): """ @@ -141,15 +190,16 @@ def mono_energy_set(hv_eV,verbose=True): Previously: SetMono """ hv_min, hv_max = mono_energy_range() + pv = mono_pvs()['energy_sp'] if hv_min <= hv_eV <= hv_max: - caput("29idmono:ENERGY_SP",hv_eV,wait=True,timeout=60) + caput(pv,hv_eV,wait=True,timeout=60) time.sleep(2.5) mono_status = mono_status_get() while True: if mono_status() > 1: mono_resest_pitch() - caput("29idmono:ENERGY_SP",hv_eV,wait=True,timeout=60) + caput(pv,hv_eV,wait=True,timeout=60) time.sleep(2.5) else: break @@ -160,8 +210,8 @@ def mono_scan_pvs(): """ returns the pvs to be used in scanning """ - val_pv = "29idmono:ENERGY_SP" - rbv_pv = "29idmono:ENERGY_MON" + val_pv = mono_pvs()['energy_sp'] + rbv_pv = mono_pvs()['energy'] return val_pv, rbv_pv def mono_status_get(): @@ -172,15 +222,14 @@ def mono_status_get(): Previously Mono_Status """ - pvs = mono_get_all_extended()['ENERGY_MON'] - MIR_P_status = pvs['MIR_P_status'] - GRT_P_status = pvs['GRT_P_status'] - MIR_X_status = pvs['MIR_P_status'] - GRT_X_status = pvs['GRT_P_status'] - MIR_status = MIR_P_status * MIR_X_status - GRT_status = GRT_P_status * GRT_X_status - return MIR_status*GRT_status - + pvs = mono_pvs()['energy'] + mir_P_status = caget(pvs['mir_P_status']) + grt_P_status = caget(pvs['grt_P_status']) + mir_X_status = caget(pvs['mir_P_status']) + grt_X_status = caget(pvs['grt_P_status']) + mirror_status = mir_P_status * mir_X_status + grating_status = grt_P_status * grt_X_status + return mirror_status*grating_status def mono_grating_translate(grating,verbose=True): @@ -201,8 +250,9 @@ def mono_grating_translate(grating,verbose=True): print_warning_message(grating+' not a valid grating') if current_grating != grating: - caput("29idmonoGRT_TYPE_SP",grating_state,wait=True,timeout=18000) # HEG - caput("29idb:gr:move",1,wait=True,timeout=18000) + pvs=mono_pvs() + caput(pvs['grt_type_sp'],grating_state,wait=True,timeout=18000) + caput(pvs['grt_move'],1,wait=True,timeout=18000) while True: if mono_status_get() > 1: time.sleep(5) @@ -224,6 +274,7 @@ def mono_resest_pitch(): Previoulsy part of SetMono """ caput("29idmonoMIR:P.STOP",1) + time.sleep(1) caput("29idmonoGRT:P.STOP",1) time.sleep(1) print('Mono pitch was reset') @@ -285,15 +336,36 @@ def mono_cff_print(): Previously: Get_CFF """ d = mono_get_all_extended - CFF = d['CFF'] - TUN0 = d['TUN0'] - TUN1 = d['TUN1'] - TUN2 = d['TUN2'] - TUN3 = d['TUN3'] - ARM = d['ARM'] - print(" cff : "+"%.4f" % CFF , " exit arm: "+"%.1f" % ARM,"mm") - print(" tun0 : "+"%.4e" % TUN0 , " tun1: "+"%.4e" % TUN1) - print(" tun2 : "+"%.4e" % TUN2 , " tun3: "+"%.4e" % TUN3) + cff = d['cff'] + tun0 = d['grt_tun0'] + tun1 = d['grt_tun1'] + tun2 = d['grt_tun2'] + tun3 = d['grt_tun3'] + arm = d['arm'] + print(" cff : "+"%.4f" % cff , " exit arm: "+"%.1f" % arm,"mm") + print(" tun0 : "+"%.4e" % tun0 , " tun1: "+"%.4e" % tun1) + print(" tun2 : "+"%.4e" % tun2 , " tun3: "+"%.4e" % tun3) + +def mono_parameters_pv(grt_num=None,mir_num=None): + """ + returns dictionary with mono_parameter for current grating/mirror + """ + if grt_num is None: + grt_num = mono_grating_num()() + if mir_num is None: + mir_num = mono_mirror_num()() + + ext = mono_extensions() + + d={ + 'mir_offset':"29idmonoMIR:P_OFFSETS."+ext[mir_num], + 'mir_pos':"29idmonoMIR:X_DEF_POS."+ext[mir_num], + 'grt_offset':"29idmonoGRT:P_OFFSETS."+ext[grt_num], + 'grt_pos':"29idmonoGRT:X_DEF_POS."+ext[grt_num], + 'grt_density':"29idmonoGRT:TYPE_CALC."+ext[grt_num], + 'grt_b2':"29idmonoGRT:B2_CALC."+ext[grt_num] + } + return d def mono_parameters_get(): @@ -310,20 +382,22 @@ def mono_parameters_get(): #MIR txt="MonoParm[\'"+date+"\']= {\n\t" for i in range(0,len(mirList)): - mir=mirList[i] - offset=caget("29idmonoMIR:P_OFFSETS."+pvList[i]) - position=caget("29idmonoMIR:X_DEF_POS."+pvList[i]) + d = mono_parameters_pv(mir_num=i) + mir = mirList[i] + offset = caget(d['mir_offset']) + position = caget(d['mir_pos']) txt+="\'"+mir+"\':["+str(offset)+","+str(position)+"]," #GRT txt+="\n\t" for i in range(0,len(grtList)): - grt=grtList[i] - offset=caget("29idmonoGRT:P_OFFSETS."+pvList[i]) - position=caget("29idmonoGRT:X_DEF_POS."+pvList[i]) - spacing=caget("29idmonoGRT:TYPE_CALC."+pvList[i]) - b2=caget("29idmonoGRT:B2_CALC."+pvList[i]) - txt+="\'"+grt+"\':["+str(offset)+","+str(position)+","+str(spacing)+","+str(b2)+"]," + d = mono_parameters_pv(grt_num=i) + grt = grtList[i] + offset = caget(d['grt_offset']) + position = caget(d['grt_pos']) + density = caget(d['grt_density']) + b2 = caget(d['grt_b2']) + txt+="\'"+grt+"\':["+str(offset)+","+str(position)+","+str(density)+","+str(b2)+"]," txt+="}" print(txt) @@ -391,7 +465,7 @@ def mono_temperature_interlock(): -def mono_scan_fillin(mda,hv_start,hv_stop,hv_step,**kwargs): +def mono_scan_fillin(hv_start,hv_stop,hv_step,**kwargs): """ fills in the scanRecord for scanning the mono @@ -405,13 +479,13 @@ def mono_scan_fillin(mda,hv_start,hv_stop,hv_step,**kwargs): #Setting up the ScanRecord for Mono in Table mode val_pv, rbv_pv = mono_scan_pvs() - mda.fillin(val_pv,rbv_pv,hv_start,hv_stop,hv_step,**kwargs) + BL.mda.fillin(val_pv,rbv_pv,hv_start,hv_stop,hv_step,**kwargs) #mono needs to stay and have a longer settling time - mda.positioner_after_scan("STAY") + BL.mda.positioner_after_scan("STAY") -def mono_scan_fillin_table(mda,hv_array,**kwargs): +def mono_scan_fillin_table(hv_array,**kwargs): """ fills in the scanRecord for scanning the mono @@ -425,73 +499,20 @@ def mono_scan_fillin_table(mda,hv_array,**kwargs): #Setting up the ScanRecord for Mono in Table mode val_pv, rbv_pv = mono_scan_pvs() - mda.fillin.table(val_pv,rbv_pv,hv_array,**kwargs) + BL.mda.fillin.table(val_pv,rbv_pv,hv_array,**kwargs) #mono needs to stay and have a longer settling time - mda.positioner_settling_time(kwargs['positioner_settling_time']) - mda.positioner_after_scan("STAY") + BL.mda.positioner_settling_time(kwargs['positioner_settling_time']) + BL.mda.positioner_after_scan("STAY") -def mono_scan_after(mda,**kwargs): +def mono_scan_after(**kwargs): """ resets mda after scanning the mono """ - after_scan_pv = mda.default_after_scan_seq + after_scan_pv = BL.mda.default_after_scan_seq caput(after_scan_pv+".PROC",1) - mda.positioner_after_scan("PRIOR POS") - -def mono_grating_offset_get(ext): - """ - gets the grating offset for the grating specified by ext - ext in ['C','D','E'] => mono_grating_names() - """ - return caget("29idmonoGRT:P_OFFSETS."+ext) + BL.mda.positioner_after_scan("PRIOR POS") -def mono_grating_offset_set(ext,val): - """ - sets the grating offset for the grating specified by ext - ext in ['C','D','E'] => mono_grating_names() - """ - return caput("29idmonoGRT:P_OFFSETS."+ext,val) - -def mono_mirror_offset_get(ext): - """ - gets the grating offset for the grating specified by ext - ext in ['C','D','E'] => mono_mirror_names() - """ - return caget("29idmonoMIR:P_OFFSETS."+ext) - -def mono_mir_offset_set(ext,val): - """ - sets the grating offset for the grating specified by ext - ext in ['C','D','E'] => mono_mirror_names() - """ - return caput("29idmonoMIR:P_OFFSETS."+ext,val) - - -def mono_grating_mirror_offsets_set(mirror_offset): - """ - changes the mirror and grating offsets to maintain parallelism - After determining parallelism (zero order a=b) - Get the correct take-off angle delta, equivalent to scan ExitSlit_Vcenter - """ - - energy_sp = mono_energy_get() - mirror_offset_old = mono_mirror_offset_get(current_mirror_ext) - - grating_offsets=[] - for ext in ['C','D','E']: - grating_offsets.append(mono_mirror_offset_get(ext)) - mir_grt_offsets = mirror_offset_old-np.array(grating_offsets) # list of MIR-GRT for all 3 gratings - - current_mirror_ext = ext[mono_get_all_extended(verbose=False)['mirror_state']] - mono_mir_offset_set(current_mirror_ext,mirror_offset) - - for ext,i in enumerate(['C','D','E']): - mono_grating_offset_set(ext,mirror_offset - mir_grt_offsets[i]) - - time.sleep (1) - mono_energy_set(energy_sp) - mono_get_all_extended(verbose=True) ############################################################################################################## ################################ aligmnent and commissioning ############################## @@ -515,7 +536,7 @@ def mono_motor_scan_pvs(motor): rbv_pv = "29idmono"+motor+"_MON" return val_pv,rbv_pv -def mono_motor_scan_fillin(mda,motor,start,stop,step,**kwargs): +def mono_motor_scan_fillin(motor,start,stop,step,**kwargs): """ for pitch motor => MIR:P or GRT:P for translation motor => MIR:X or GRT:X @@ -525,9 +546,7 @@ def mono_motor_scan_fillin(mda,motor,start,stop,step,**kwargs): val_pv,rbv_pv = mono_motor_scan_pvs(motor) caput(val_pv+".PREC",3) # database sets .PREC==0. We want more digits than that. - mda.fillin(val_pv,rbv_pv,start,stop,step,**kwargs) - - + BL.mda.fillin(val_pv,rbv_pv,start,stop,step,**kwargs) def mono_zero_order(angle): """ @@ -543,6 +562,23 @@ def mono_zero_order(angle): caput("29idmonoGRT:P_MOVE_CMD.PROC",1,wait=True,timeout=18000) print("Mono set to zero order: MIR_pitch = "+str(angle)+", GRT_pitch = "+str(angle)) +def mono_angles_set(alpha,beta): #JM modified to monitor the ready, moving sequentialy ended up in crash sometimes + """ + Sets the mirror pitch (alpha) and grating pitch (beta) angles + + Previously: Mono_angle + """ + alpha=alpha*1.0 + beta=beta*1.0 + #Putting Setpoints Go + caput("29idmonoGRT:P_SP",alpha) + caput("29idmonoMIR:P_SP",beta) + ready=0 + while ready != 1: + time.sleep(0.1) + ready=caget('29idmono:ERDY_STS') + print("Mono set to zero order: MIR_pitch = "+str(alpha)+", GRT_pitch = "+str(beta)) + def mono_pink_beam(): """ moves grating and mirror out of beam @@ -572,5 +608,132 @@ def mono_CC(): caput("29idmonoMIR:X_DCPL_CALC.PROC",0) caput("29idmonoGRT_TYPE_SP", 10) caput("29idmonoGRT:X_DCPL_CALC.PROC",0) - ev=caget("29idmono:ENERGY_SP") + caput("29idmono:ENERGY_SP", 440) + +def mono_grating_offset_set(val,grt_num=None): + """ + sets the grating offset for the grating + + Previously: Mono_Set_GRT0 + """ + pvs=mono_pvs(grt_num,None) + caput(pvs['grt_offset'],val) + mono_get_all_extended(verbose=True) + +def mono_mirror_offset_set(val,mir_num=None): + """ + sets the mirror offset for the grating + + Previously: Mono_Set_MIR0 + """ + pvs=mono_pvs(None,mir_num) + caput(pvs['mir_offset'],val) + mono_get_all_extended(verbose=True) + +def mono_grating_mirror_offsets_set(mirror_offset): + """ + changes the mirror and grating offsets to maintain parallelism + After determining parallelism (zero order a=b) + Get the correct take-off angle delta, equivalent to scan ExitSlit_Vcenter + + Previously: Mono_Set_MIR0_GRT0,MIR_GRT_Offset,Mono_Set_MIR0_GRT0_all + """ + current_vals = mono_get_all_extended(verbose=False) + energy_sp = current_vals['energy_sp'] + mirror_offset_old = current_vals['mir_offset'] + + #get current grating offsets + grating_offsets=[] + for grt_num in range(0,3): + grating_offsets.append(mono_parameters_pv(grt_num=grt_num,mir_num=None)['grt_offset']) + + #calc mirror_offset - grating_grating + mir_grt_offsets = mirror_offset_old-np.array(grating_offsets) # list of MIR-GRT for all 3 gratings + + #set mirror_offset + mono_mirror_offset_set(mirror_offset) + + #set grating_offsets + for grt_num in range(0,3): + mono_grating_offset_set(mirror_offset - mir_grt_offsets[grt_num],grt_num) + + time.sleep (1) + mono_energy_set(energy_sp) + mono_get_all_extended(verbose=True) + + +def mono_grating_b2_set(val,grt_num=None): + """ + sets the grating offset for the grating + Previously: Mono_Set_b2 + """ + hv = mono_energy_get() + pvs = mono_pvs(grt_num,None) + caput(pvs['grt_b2t'],val) + time.sleep(1) + + mono_energy_set(hv) + mono_get_all_extended(verbose=True) + +def mono_cff_set(val,tune_num): + """ + sets the tuning parameters for the cff calculation + tune_num = order + + Previously: Mono_Set_cff + """ + hv = mono_energy_get() + pvs = mono_pvs() + + #get current info + current_vals = mono_get_all_extended(verbose=False) + grt_pitch = current_vals['grt_pitch'] + mir_pitch = current_vals['mir_pitch'] + print ('Pitch grating, mirror: ',grt_pitch,mir_pitch) + + #set the tuning coeffient + tun='tun'+str(tune_num) + caput(pvs[tun],val) + time.sleep(1) + + #set then energy + mono_energy_set(hv) + + #print differences in pitch + mono_get_all_extended(verbose=False) + grt_dif = grt_pitch-current_vals['grt_pitch'] + mir_dif = mir_pitch-current_vals['mir_pitch'] + + print('Pitch grating, mirror: ',current_vals['grt_pitch'],current_vals['mir_pitch']) + print('Differences : ',grt_dif,mir_dif) + +def mono_arm_set(distance_mm): + """ + sets the exit arm for the grating + + Previously: Mono_Set_ExitArm + """ + hv = mono_energy_get() + pvs = mono_pvs() + + #get current info + current_vals = mono_get_all_extended(verbose=False) + grt_pitch = current_vals['grt_pitch'] + mir_pitch = current_vals['mir_pitch'] + print ('Pitch grating, mirror: ',grt_pitch,mir_pitch) + + #set the exit arm + caput("29idmono:PARAMETER.G",distance_mm) + time.sleep(1) + + #set then energy + mono_energy_set(hv) + + #print differences in pitch + mono_get_all_extended(verbose=False) + grt_dif = grt_pitch-current_vals['grt_pitch'] + mir_dif = mir_pitch-current_vals['mir_pitch'] + + print('Pitch grating, mirror: ',current_vals['grt_pitch'],current_vals['mir_pitch']) + print('Differences : ',grt_dif,mir_dif) \ No newline at end of file diff --git a/instruments/beamline.py b/instruments/beamline.py index 1927eab176f93e355c22d49d37c3d54e42946437..c4d045ac683cff917e1cce371f88e4216b6463b5 100644 --- a/instruments/beamline.py +++ b/instruments/beamline.py @@ -25,13 +25,13 @@ def scan_fillin(VAL,RBV,start,stop,steps_points,**kwargs): """ fills in the scan record for the curretn beamline ioc """ - mda.fillin(VAL,RBV,start,stop,steps_points,**kwargs) + BL.mda.fillin(VAL,RBV,start,stop,steps_points,**kwargs) def scan_fillin_table(VAL,RBV,my_table,**kwargs): """ fills in the scan record for the curretn beamline ioc """ - mda.fillin_table(VAL,RBV,my_table,**kwargs) + BL.mda.fillin_table(VAL,RBV,my_table,**kwargs) def scan_go(**kwargs): """ @@ -42,7 +42,7 @@ def scan_go(**kwargs): X-ray = True (default), does shutter checks = False no shutter checks """ - mda.go(verbose=True,**kwargs) + BL.mda.go(verbose=True,**kwargs) def last_mda(): @@ -50,7 +50,7 @@ def last_mda(): returns the last mda file number in the ioc defined by BL_ioc Previously: LastMDA """ - filenum = mda.lastFileNum() + filenum = BL.mda.lastFileNum() return filenum diff --git a/instruments/cameras.py b/instruments/cameras.py index a217499e3d4c83e66e5d189441669b946d1f8358..a0202922ccf686edc7971f89484ec6b9aa0cd21c 100644 --- a/instruments/cameras.py +++ b/instruments/cameras.py @@ -43,3 +43,200 @@ def Cam_FreeStrSeq(camNUM): caput(pvIOC+"userStringSeqEnable.VAL",1) +def Cam_ScanSetup(mda,scanDIM,camNUM): #individual files saving + pvCam="29id_ps"+str(camNUM)+":" + pvIOC=mda.ioc + #beforscan + Cam_SaveStrSeq(camNUM) + caput(pvIOC+"scan"+str(scanDIM)+".BSPV",pvIOC+"userStringSeq2.PROC") + #scan record (filename and trigger) + nextfile=str(caget(pvIOC+"saveData_baseName"))+str(caget(pvIOC+"saveData_scanNumber")) + filepath=caget(pvIOC+"saveData_fileSystem") + filepath="/net"+filepath[1:len(filepath)]+"/tif" + caput(pvCam+"TIFF1:FilePath",filepath) + caput(pvCam+"TIFF1:FileName",nextfile) + caput(pvCam+"TIFF1:FileWriteMode","Single") + caput(pvIOC+"scan1.T2PV",pvCam+"cam1:Acquire") + #afterscan + Cam_FreeStrSeq(camNUM) + caput(pvIOC+"scan"+str(scanDIM)+".ASPV",pvIOC+"userStringSeq1.PROC") + caput(pvIOC+"scan1.ASCD",1) + print("DON'T FORGET TO CLEAR SCAN RECORD AT THE END OF THE SCRIPT!!!!! ") + print("Use Script: Cam_ScanClear(scanIOC,scanDIM)") + + + +def Cam_FreeRun(camNUM): + camNUM=str(camNUM) + pv="29id_ps"+camNUM+":" + caput(pv+"TIFF1:AutoSave",0) + caput(pv+"TIFF1:EnableCallbacks",0) + sleep(0.5) + caput(pv+"cam1:ImageMode",2) + caput(pv+"cam1:Acquire",1) + caput(pv+"cam1:AcquireTime",0.015) + caput(pv+"cam1:AcquirePeriod",0.030) + print("Cam"+str(camNUM)+": Free run mode") + + + + + +def Cam_SaveMode(camNUM): + camNUM=str(camNUM) + pv="29id_ps"+camNUM+":" + caput(pv+"cam1:Acquire",0) + sleep(0.5) + caput(pv+"cam1:ImageMode",0) + caput(pv+"TIFF1:AutoSave",1) + caput(pv+"TIFF1:EnableCallbacks",1) + caput(pv+"TIFF1:FileNumber",1) + caput(pv+"cam1:AcquireTime",0.015) + caput(pv+"cam1:AcquirePeriod",0.030) + print("Cam"+str(camNUM)+": Saving mode") + +def Cam_Start(camNUM): + Cam_FreeRun(camNUM) + +def Cam_Stop(camNUM): + camNUM=str(camNUM) + pv="29id_ps"+camNUM+":" + caput(pv+"cam1:Acquire",0) + + + +def Cam_ROI_SetUp(xstart,ystart,xsize,ysize,camNUM,roiNUM=1,binX=1,binY=1): + pv="29id_ps"+str(camNUM)+":ROI"+str(roiNUM)+':' + caput(pv+'MinX',xstart) + caput(pv+'MinY',ystart) + caput(pv+'SizeX',xsize) + caput(pv+'SizeY',ysize) + caput(pv+'BinX',binX) + caput(pv+'BinY',binY) + caput(pv+'EnableCallbacks','Enable') + print(('ROI'+str(roiNUM)+' - '+caget(pv+'EnableCallbacks_RBV',as_string=True))) + +def Cam_ROI_Stats(xstart,ystart,xsize,ysize,camNUM,roiNUM=1,binX=1,binY=1): + pv="29id_ps"+str(camNUM)+":Stats1:" + Cam_ROI_SetUp(xstart,ystart,xsize,ysize,camNUM,roiNUM,binX,binY) + caput(pv+'EnableCallbacks','Enable') + roi=caget(pv+'NDArrayPort_RBV',as_string=True) + print((roi+' Stats => '+pv+'Total_RBV')) + print('To set-up as detector use:') + print('Cam_ROI_Det(detNUM,scanIOC,camNUM='+str(camNUM)+',roiNUM='+str(roiNUM)+')') + +def Cam_ROI_Det(detNUM,scanIOC,camNUM,roiNUM,scanDIM=1): + pvdet='29id'+scanIOC+':scan'+str(scanDIM)+'.D'+str(detNUM)+'PV' + pvroi="29id_ps"+str(camNUM)+":Stats1:Total_RBV" + caput(pvdet,pvroi) + print('ROI stats set up as detector D'+str(detNUM)+' in '+scanIOC+' scan'+str(scanDIM)) + +### Scan Record Set-Up: + +def Scan_Cam_Go(mda,VAL,RBV,scanDIM,start,stop,step,camNUM): + mda.fillin(scanDIM,VAL,RBV,start,stop,step) + Cam_ScanSetup(scanDIM,camNUM) + + caput("29id"+scanIOC+":scan"+str(scanDIM)+".PASM","STAY") + + # Scan_Go() without Before_After_Scan() + BL_mode=BL_Mode_Read()[0] + if BL_mode != 2: + Check_MainShutter() + FileName = caget("29id"+scanIOC+":saveData_baseName",as_string=True) + FileNum = caget("29id"+scanIOC+":saveData_scanNumber") + print(FileName+": #"+str(FileNum)+" started at ", dateandtime()) + caput("29id"+scanIOC+":scan"+str(scanDIM)+".EXSC",1,wait=True,timeout=900000) #pushes scan button + print(FileName+": #"+str(FileNum)+" finished at ", dateandtime()) + + Cam_ScanClear(scanIOC,scanDIM) + caput("29id"+scanIOC+":scan"+str(scanDIM)+".PASM","PRIOR POS") + +def Scan_Cam_Pos2_Go(VAL1,RBV1,VAL2,RBV2,scanDIM,start1,stop1,step1,start2,stop2,camNUM): + scanIOC=BL_ioc() + pvCam="29id_ps"+str(camNUM)+":" + Cam_ScanSetup(scanDIM,camNUM) + Scan_FillIn(VAL1,RBV1,scanIOC,scanDIM,start1,stop1,step1) + Scan_FillIn_Pos2(VAL2,RBV2,scanIOC,scanDIM,start2,stop2) + caput("29id"+scanIOC+":scan"+str(scanDIM)+".PASM","STAY") + mda.goScan_Go(scanIOC,scanDIM=1 ) + Cam_ScanClear(scanIOC,scanDIM) + caput("29id"+scanIOC+":scan"+str(scanDIM)+".PASM","PRIOR POS") + +def Cam_ScanClear(scanIOC,scanDIM): + caput("29id"+scanIOC+":scan"+str(scanDIM)+".BSPV","") + caput("29id"+scanIOC+":scan"+str(scanDIM)+".ASPV","") + caput("29id"+scanIOC+":scan"+str(scanDIM)+".T2PV","") + caput("29id"+scanIOC+":scan"+str(scanDIM)+".DDLY",0.5) + #print "Scan Record cleared from Camera Settings" + +### Image Acquisition: + +def TakeImageSetFolder(camNUM,NewFolder=""): + scanIOC=BL.ioc + pvCam="29id_ps"+str(camNUM)+":" + pvIOC="29id"+scanIOC+":" + #beforscan + Cam_SaveMode(camNUM) + #FilePath + filepath=caget(pvIOC+"saveData_fileSystem")+"/tif" + filepath="/net"+filepath[1:len(filepath)]+"/"+NewFolder + caput(pvCam+"TIFF1:FilePath",filepath) + print("WARNING: Make sure NewFolder exists !!!") + +def TakeImageSetFileNum(camNUM,n): + scanIOC=BL.mda.ioc + pvCam="29id_ps"+str(camNUM)+":" + pvIOC="29id"+scanIOC+":" + #beforscan +# Cam_SaveMode(camNUM) + #Filename + if n<10: + nextfile="29id"+scanIOC+"_000"+str(n) + elif n<100: + nextfile="29id"+scanIOC+"_00"+str(n) + elif n<1000: + nextfile="29id"+scanIOC+"_0"+str(n) + elif n<10000: + nextfile="29id"+scanIOC+"_"+str(n) + caput(pvCam+"TIFF1:FileName",nextfile) + caput(pvCam+"TIFF1:AutoIncrement",1) + caput(pvCam+"TIFF1:FileNumber",2) + +def TakeImageSetup(camNUM): + scanIOC=BL.mda.ioc + pvCam="29id_ps"+str(camNUM)+":" + pvIOC="29id"+scanIOC+":" + #beforscan + Cam_SaveMode(camNUM) + #Filename + nextfile=str(caget(pvIOC+"saveData_baseName"))+str(caget(pvIOC+"saveData_scanNumber")-1) + filepath=caget(pvIOC+"saveData_fileSystem")+"/tif" + if scanIOC == "Test": + filepath="/"+filepath[1:len(filepath)] # for 29idTest + else: + filepath="/net"+filepath[1:len(filepath)] # for 29idb/c/d + + caput(pvCam+"TIFF1:FilePath",filepath) + caput(pvCam+"TIFF1:FileName",nextfile) + #afterscan + +def TakeImage(camNUM,AcqTime): + AcqPeriode=AcqTime+0.040 + pvCam="29id_ps"+str(camNUM)+":" + caput(pvCam+"cam1:AcquireTime",AcqTime) + caput(pvCam+"cam1:AcquirePeriod",AcqPeriode) + sleep(1) + caput(pvCam+"cam1:Acquire",1,wait=True,timeout=500) + sleep(1) + TiffNum =caget(pvCam+"TIFF1:FileNumber_RBV")-1 + FileName= caget(pvCam+"TIFF1:FileName_RBV",as_string=True) + print("\n"+FileName+": #"+str(TiffNum)+" started at ", dateandtime()) + print("\n================================================\n") + + + + + + + diff --git a/instruments/diagnostics.py b/instruments/diagnostics.py index dffb409716bfc4f3232f6cbc5f3ecafb2919d47d..d22bca803ed3c14414eecf05389ff3dccdc026ae 100644 --- a/instruments/diagnostics.py +++ b/instruments/diagnostics.py @@ -8,7 +8,6 @@ from IEX_endstations import * ############################################################################################################## ###### We should make pvs in the 29idb ioc to hold these values: - def diagnostics_dict(): """ Dictionary of Diagnostic positions In and Out by either motor number or name @@ -59,10 +58,10 @@ def diagnostic(diagnostic_name,in_out): caput("29idb:m"+str(motor)+".VAL",position,wait=True,timeout=18000) print("\n"+name+": "+ in_out) -def diagnostics_all_out(diode_to_stay_in=False): +def diagnostics_all_out(diode_stay_in=False): """ Retracts all diagnostic - diode_to_stay_in = True / False (checks beamline) / 'c' /'d' + diode_to_stay_in = True / False (checks beamline) Previously: AllDiagOut """ @@ -70,12 +69,12 @@ def diagnostics_all_out(diode_to_stay_in=False): text="" #which motor is Diode of interest - if diode_to_stay_in: - diode_to_stay_in = BL.branch + if diode_stay_in: + branch = BL.branch - if diode_to_stay_in.lower() == 'c': + if branch == 'c': diode_motor=diag["motor"]["gas-cell"] - elif diode_to_stay_in.lower() == 'd': + elif branch == 'd': diode_motor=diag["motor"]["D5D"] else: diode_motor=None @@ -83,7 +82,7 @@ def diagnostics_all_out(diode_to_stay_in=False): #Taking out the diagnostic for motor in list(diag["Out"].keys()): if motor is diode_motor: - text=' except Diode-'+diode_to_stay_in + text=' except Diode-'+BL.branch #putting Diode In if not already in -JM position=diag["In"][motor] caput("29idb:m"+str(motor)+".VAL",position,wait=True,timeout=18000) diff --git a/instruments/electron_analyzer.py b/instruments/electron_analyzer.py index e3429fd44be9b176410e638c69866bbf66222a6f..4427551dd4ada4e365e7d77052ff1e5b5919c554 100644 --- a/instruments/electron_analyzer.py +++ b/instruments/electron_analyzer.py @@ -28,7 +28,8 @@ from .Scienta import * def __main__(): global EA EA = Scienta() - + +mda = BL.mda ########################################################################### def EA_ioc_init(**kwargs): diff --git a/instruments/encoders.py b/instruments/encoders.py new file mode 100644 index 0000000000000000000000000000000000000000..e45ab7f7e1b56991740af37e3e0dd33c1d1086f4 --- /dev/null +++ b/instruments/encoders.py @@ -0,0 +1,62 @@ +from epics import caput,caget + +def encoder_dictionary_entry(name): + """ + returns a dictionary with the encoder pvs + encoder_dictionary_entry(name) = encoder_ioc, motor_ioc, encoder_list + + """ + d={ + 'slit2B':("29idMini1:",[13,14,15,16]), + 'slit3D':("29idMini2:",[26,27]), + 'ARPES':("ARPES:"),[1,2,3,4]) + } + return d[name] + +def encoder_sync(name): + """ + sync all the encoders for name + """ + encoder_ioc, motor_ioc, encoder_list = encoder_dictionary_entry(name) + for encoder_num in encoder_list: + pv = motor_ioc+":m"+str(encoder_num)+".SYNC" + caput(pv,1) + +def encoders_reset(name,Hcenter,Vcenter): + """ + Resetting Slit 2B encoders to 0 for a given position (Hcenter,Vcenter). + Slit size need to be set to 0. + + Previously: Reset_Slit2B_Encoders + """ + encoder_sync('name') + encoder_ioc, motor_ioc, encoder_list = encoder_dictionary_entry(name) + + print('\nCurrent Position:') + for e_num in encoder_list: + pv = encoder_ioc+'e'+(e_num)+'Pos' + print('e'+(e_num)+' = '+str(caget(pv))) + + print('\nSetting all Offsets to 0:') + for e_num in encoder_list: + pv = encoder_ioc+'e'+(e_num)+'Pos.EOFF' + caput(pv,0) + + print('\nCurrent Position:') + for e_num in encoder_list: + pv = encoder_ioc+'e'+(e_num)+'Pos' + print('e'+(e_num)+' = '+str(caget(pv))) + + print('\nSetting back Offsets:') + for e_num in encoder_list: + pos_pv = encoder_ioc+'e'+(e_num)+'Pos' + offset_pv = encoder_ioc+'e'+(e_num)+'Pos.EOFF' + caput(offset_pv,-caget(pos_pv)) + + print('\nCurrent Position:') + for e_num in encoder_list: + pv = encoder_ioc+'e'+(e_num)+'Pos' + print('e'+(e_num)+' = '+str(caget(pv))) + + encoder_sync(name) + print('sync '+name) diff --git a/instruments/logfile.py b/instruments/logfile.py index c07e582398ded480f095cdb9a44a4fbf3617714b..91a20236e815c0c8df94d407133173d816443595 100644 --- a/instruments/logfile.py +++ b/instruments/logfile.py @@ -92,7 +92,7 @@ def logfile_fpath(endstation_name,mda_ioc): try: filename = logfile_name_get(endstation_name) - user_name = mda.scanRecord_user(mda_ioc) + user_name = BL.mda.scanRecord_user(mda_ioc) fpath_with_subfolder = join(user_name,filename) except: fpath_with_subfolder = "logfile.txt" @@ -137,7 +137,7 @@ def logfile_header(endstation_name,mda_ioc,header_list): fpath_with_subfolder=logfile_fpath(endstation_name,mda_ioc) with open(fpath_with_subfolder, "w+") as f: f.write('@Log version: '+ version+'\n\n') - file_path = mda.scanRecord_filepath(mda_ioc) + file_path = BL.mda.scanRecord_filepath(mda_ioc) f.write('FilePath '+endstation_name+': '+file_path+'\n') for key in header_list.keys(): diff --git a/instruments/m3r.py b/instruments/m3r.py index bf76f19e803e6c966cfec9522cd805a6042c4465..903ed76680384b85c7073612c5d2a61d783cf6d8 100644 --- a/instruments/m3r.py +++ b/instruments/m3r.py @@ -1,7 +1,10 @@ from cgi import print_arguments -from IEX_beamline.utilities import print_warning_message + from epics import caget, caput -from FMB_mirrors import * + +from .utilities import print_warning_message +from .FMB_mirrors import * + ############################################################################################################## ################################ M3R ############################## ############################################################################################################## diff --git a/instruments/mpa.py b/instruments/mpa.py index 73f2ebe895cedb842003269cb303c577092c47ab..f941431c5f1d437bcc0a65e60ee471d32bde1784 100644 --- a/instruments/mpa.py +++ b/instruments/mpa.py @@ -1,11 +1,13 @@ from time import sleep from os.path import dirname, join -from math import floor +import socket from epics import caget, caput from .userCalcs import userCalcOut_clear,userStringSeq_clear -from .Kappa import Kappa_motor_dictionary,Kappa_cts, mda, Kappa_scaler_pv +from .Kappa import Kappa_motor_dictionary,Kappa_cts, mda from .AD_utilites import AD_ROI_setup +from .scalers import scaler_cts +from scanRecord import * """ @@ -16,10 +18,15 @@ To do, get busy record in the mpa ioc, get user calcs in the mpa ioc ############################################################################################################## ############################## PVs ############################## ############################################################################################################## - mpa_pv = "29iddMPA:" -mpa_busy="29idcScienta:mybusy2" -userCalc_pv="29idTest" +mpaDet_pv = mpa_pv + "det1:" +mpa_busy = "29idcScienta:mybusy2" +userCalc_pv = "29idTest" +DAC_pv = '29iddau1:dau1:011:DAC' +max_HV = 2990 +ratio = 500 +tth_dLLM=13.73 +tth_dHLM=23.73 def mpa_reset_pv(): @@ -165,74 +172,92 @@ def mpa_ROI_stats(ROI_num): caput(stats_pv+'ComputeCentroid','Yes') caput(stats_pv+'ComputeProfiles','Yes') -def _mpa_trigger_callback(BeforeAfter,saveImg=False,**kwargs): +def _mpa_trigger_calcOut(**kwargs): """ - used for triggering the MPA in the scanRecord, reset Proc1 and waits for finish - - BeforeAfter = before, sets up and puts trigger in detTrigNum - = after, clear detTrigNum amd resets to defaults - - saveImg = False used for appropriate trigger of ROIs - = True also saves an image based on ADplugin type - - by default ADplugin = 29iddMPA:TIFF1: - can use 29iddMPA:HDF1: + writes strSeq and calcOut for MPA this should go into the IOC + + **kwargs: + ADplugin = 'TIFF1:' (default) """ - kwargs.setdefault("ADplugin","29iddMPA:TIFF1:") + kwargs.setdefault("ADplugin","TIFF1:") + kwargs.setdefault("save_image",False) - userCalc_pv="29idTest" - PVstr1="29idTest:userStringSeq1" - PVstr2="29idTest:userStringSeq2" - PVcalcOut9="29idTest:userCalcOut9" - PVcalcOut10="29idTest:userCalcOut10" + ADplugin = mpa_pv + kwargs["ADplugin"] + Proc1 = mpa_pv + "Proc1:" - ADplugin=kwargs["ADplugin"] - Proc1=mpa_pv+"Proc1:" + #All this should moved into the MPA IOC + Calcs_mda = ScanRecord("29idTest:") - #All this should moved into the MPA IOC + desc = "MPA busy" + n=9 + busy_CalcOut = userCalcOut_clear(Calcs_mda,n) + caput(busy_CalcOut+".DESC",desc) + caput(busy_CalcOut+".INPA",mpa_busy+" CP") + caput(busy_CalcOut+".OOPT",'Transition to non-zero') + caput(busy_CalcOut+".OUT",start_strSeq+".PROC PP") + + desc = "MPA start" + n=1 + start_strSeq = userStringSeq_clear(Calcs_mda,n) + caput(start_strSeq+".DESC",desc) + caput(start_strSeq+".LNK1", Proc1+"ResetFilter PP") + caput(start_strSeq+".STR1","Yes") + + desc = "MPA wait" + n=10 + wait_CalcOut = userCalcOut_clear(Calcs_mda,n) + caput(wait_CalcOut+".DESC",desc) + caput(wait_CalcOut+".INPA",Proc1+"NumFilter_RBV") + caput(wait_CalcOut+".INPB",Proc1+"NumFiltered_RBV") + caput(wait_CalcOut+".OOPT",'Transition to non-zero') + caput(wait_CalcOut+".OUT",done_strSeq+".PROC PP") + + desc = "MPA writeDone" + n=1 + done_strSeq = userStringSeq_clear(Calcs_mda,n) + caput(done_strSeq+".DESC","MPA writeDone") + caput(done_strSeq+".LNK1", ADplugin+"WriteFile PP") + caput(done_strSeq+".STR1","Write") + caput(done_strSeq+".LNK1", mpa_busy+" PP") + caput(done_strSeq+".STR1","Done") + - if BeforeAfter=="makeStringSeqCalcCout": - #userCalcOut9 - MPA-busy - caput(PVcalcOut9+".DESC","MPA busy") - caput(PVcalcOut9+".INPA",mpa_busy+" CP") - caput(PVcalcOut9+".OOPT",'Transition to non-zero') - caput(PVcalcOut9+".OUT",PVstr1+".PROC PP") - #Enable CalcOut10 if enable exists - #userStringSeq1 - MPA-start - caput(PVstr1+".DESC","MPA start") - caput(PVstr1+".LNK1", Proc1+"ResetFilter PP") - caput(PVstr1+".STR1","Yes") - #userCalcOut9 - MPA-Proc1waiting - caput(PVcalcOut10+".DESC","MPA Proc1waitng") - caput(PVcalcOut10+".INPA",Proc1+"NumFilter_RBV") - caput(PVcalcOut10+".INPB",Proc1+"NumFiltered_RBV") - caput(PVcalcOut10+".OOPT",'Transition to non-zero') - caput(PVcalcOut10+".OUT",PVstr2+".PROC PP") - #userStringSeq1 - MPA-writeDone - caput(PVstr2+".DESC","MPA writeDone") - caput(PVstr2+".LNK1", ADplugin+"WriteFile PP") - caput(PVstr2+".STR1","Write") - caput(PVstr2+".LNK1", Busy+" PP") - caput(PVstr2+".STR1","Done") +def _mpa_trigger_callback(trigger,saveImg=False,**kwargs): + """ + used for triggering the MPA in the scanRecord, reset Proc1 and waits for finish + + trigger: adds/removes trigger to mda (True/False) - detTrigNum=kwargs["detTrigNum"] + **kwargs: + save_image = False used for appropriate trigger of ROIs + = True also saves an image based on ADplugin type + ADplugin = 'TIFF1:' (default - if BeforeAfter=="before": + by default ADplugin = 29iddMPA:TIFF1: + can use 29iddMPA:HDF1: + """ + + kwargs.setdefault("ADplugin","TIFF1:") + kwargs.setdefault("save_image",False) + + ADplugin = mpa_pv + kwargs['ADplugin'] + + _mpa_trigger_calcOut(**kwargs) + + if trigger==True: caput(ADplugin+"AutoResetFilter","Yes") if saveImg: caput(ADplugin+"AutoSave", "No") caput(ADplugin+"EnableCallbacks", "Enable") - - if BeforeAfter=="after": + if trigger==False: caput(ADplugin+"AutoResetFilter","No") if saveImg: caput(ADplugin+"EnableCallbacks", "Disable") caput(ADplugin+"AutoSave", "Yes") - trigger=mpa_busy return mpa_busy def _mpa_prefix(**kwargs): @@ -244,136 +269,151 @@ def _mpa_prefix(**kwargs): nextMDA = mda.fileNum prefix="mda"+str.zfill(str(nextMDA),4)+"_mpa" return prefix -def MPA_Trigger(BeforeAfter, saveImg, **kwargs): + +def mpa_trigger(trigger, **kwargs): """ - Sets up the ScanRecord to trigger the MPA + Sets up / Cleans up the ScanRecord to trigger the MPA + + trigger: adds/removes trigger to mda (True/False) + - saveImg = False used for appropriate trigger of ROIs - = True also saves an image based on ADplugin type - - + **kwargs: + save_image = False used for appropriate trigger of ROIs + = True also saves an image based on ADplugin type + detTrigNum = 2 (default) + scan_dim = 1 (default) + ADplugin = "TIFF1" / "HDF1" + + Previously: MPA_Trigger """ - kwargs.setdefault("scanIOC",BL_ioc()) kwargs.setdefault("detTrigNum",2) + kwargs.setdefault("save_image",False) + kwargs.setdefault('scan_dim',1) + kwargs.setdefault("ADplugin","TIFF1:") - cnt=floor(Kappa_scaler_pv) - caput("29iddMPA:Proc1:NumFilter",cnt) - - Busy=_mpa_trigger_callback(BeforeAfter,saveImg=saveImg,**kwargs) - scanPV="29id"+kwargs["scanIOC"]+":scan"+str(kwargs["scanDIM"]) - + mpa_busy = _mpa_trigger_callback(trigger, **kwargs) + #adding the MPA to the scanRecord trigger - if BeforeAfter == "before": + if trigger == True: _mpa_prefix(**kwargs) - caput(scanPV+".T"+str(kwargs["detTrigNum"])+"PV", Busy) - - else: - caput(scanPV+".T"+str(kwargs["detTrigNum"])+"PV", "") + mda.triggers_set(kwargs['scan_dim'],{2:mpa_busy}) + + if trigger == False: + mda.triggers_set(kwargs['scan_dim'],{2:''}) -def MPA_SaveStrSeq(): - ioc="Kappa" +def mpa_save_strSeq(**kwargs): + """ + **kwargs: + ADplugin: "TIFF1:" + """ + kwargs.setdefault("ADplugin","TIFF1:") + + ADplugin = mpa_pv + kwargs["ADplugin"] + + desc = "MCP datamode" n=2 - pvDet="29iddMPA:det1:" - pvTIF="29iddMPA:TIFF1:" - pvioc="29id"+ioc+":userStringSeq"+str(n) - ClearStringSeq(ioc,n) - caput(pvioc+".DESC","MCP datamode") - caput(pvioc+".LNK1",pvDet+"Acquire CA NMS") - caput(pvioc+".STR1","Done") - caput(pvioc+".WAIT1","Wait") - caput(pvioc+".LNK2",pvDet+"RunTimeEnable PP NMS") - caput(pvioc+".STR2","1") - caput(pvioc+".WAIT2","Wait") - caput(pvioc+".LNK3",pvTIF+"EnableCallbacks PP NMS") - caput(pvioc+".STR3","1") - -def MPA_FreeStrSeq(): - ioc="Kappa" + strSeq_pv = userStringSeq_clear(mda,n) + caput(strSeq_pv+".DESC",desc) + caput(strSeq_pv+".LNK1",mpaDet_pv+"Acquire CA NMS") + caput(strSeq_pv+".STR1","Done") + caput(strSeq_pv+".WAIT1","Wait") + caput(strSeq_pv+".LNK2",mpaDet_pv+"RunTimeEnable PP NMS") + caput(strSeq_pv+".STR2","1") + caput(strSeq_pv+".WAIT2","Wait") + caput(strSeq_pv+".LNK3",ADplugin+"EnableCallbacks PP NMS") + caput(strSeq_pv+".STR3","1") + +def mpa_freerun_strSeq(): + """ + """ + desc = "MCP freerun" n=1 - pvDet="29iddMPA:det1:" - pvioc="29id"+ioc+":userStringSeq"+str(n) - ClearStringSeq(ioc,n) - caput(pvioc+".DESC","MCP freerun") - caput(pvioc+".LNK1",pvDet+"Acquire PP NMS") - caput(pvioc+".WAIT1","Wait") - caput(pvioc+".STR1","Done") - caput(pvioc+".LNK2","29iddMPA:TIFF1:EnableCallbacks PP NMS") - caput(pvioc+".STR2","0") - caput(pvioc+".WAIT2","Wait") - caput(pvioc+".LNK3",pvDet+"RunTimeEnable PP NMS") - caput(pvioc+".STR3","0") - caput(pvioc+".WAIT3","Wait") - caput(pvioc+".LNK4",pvDet+"Acquire PP NMS") - caput(pvioc+".STR4","Acquire") - - -def MPA_HV_SP_CalcOut(): - ioc="Kappa" + strSeq_pv = userStringSeq_clear(mda,n) + caput(strSeq_pv+".DESC",desc) + caput(strSeq_pv+".LNK1",mpaDet_pv+"Acquire PP NMS") + caput(strSeq_pv+".WAIT1","Wait") + caput(strSeq_pv+".STR1","Done") + caput(strSeq_pv+".LNK2","29iddMPA:TIFF1:EnableCallbacks PP NMS") + caput(strSeq_pv+".STR2","0") + caput(strSeq_pv+".WAIT2","Wait") + caput(strSeq_pv+".LNK3",mpaDet_pv+"RunTimeEnable PP NMS") + caput(strSeq_pv+".STR3","0") + caput(strSeq_pv+".WAIT3","Wait") + caput(strSeq_pv+".LNK4",mpaDet_pv+"Acquire PP NMS") + caput(strSeq_pv+".STR4","Acquire") + + +def mpa_HV_sp_calcOut(): + """ + """ + + desc = "MPA HV SP" n=9 - pvioc="29id"+ioc+":userCalcOut"+str(n) - ClearCalcOut(ioc,n) - max_HV=2990 - ratio=500 - caput(pvioc+".DESC","MPA HV SP") - caput(pvioc+".A",0) - caput(pvioc+".B",ratio) - caput(pvioc+".C",max_HV) - caput(pvioc+".CALC$","A") - caput(pvioc+".OCAL$","MIN(A/B,C/B)") - caput(pvioc+".OOPT",1) # On Change - caput(pvioc+".DOPT",1) # Use 0CALC - caput(pvioc+".IVOA",0) # Continue Normally - caput(pvioc+".OUT","29iddau1:dau1:011:DAC_Set PP NMS") - -def MPA_HV_RBV_CalcOut(): - ioc="Kappa" + calcOut_pv = userCalcOut_clear(mda,n) + + caput(calcOut_pv+".DESC",desc) + caput(calcOut_pv+".A",0) + caput(calcOut_pv+".B",ratio) + caput(calcOut_pv+".C",max_HV) + caput(calcOut_pv+".CALC$","A") + caput(calcOut_pv+".OCAL$","MIN(A/B,C/B)") + caput(calcOut_pv+".OOPT",1) # On Change + caput(calcOut_pv+".DOPT",1) # Use 0CALC + caput(calcOut_pv+".IVOA",0) # Continue Normally + caput(calcOut_pv+".OUT",DAC_pv+" PP NMS") + +def mpa_HV_rbv_calcOut(): + """ + """ + desc = "MPA HV RBV" n=10 - pvioc="29id"+ioc+":userCalcOut"+str(n) - ClearCalcOut(ioc,n) - max_HV=2750 - ratio=500 - caput(pvioc+".DESC","MPA HV RBV") - caput(pvioc+".INPA",'29iddau1:dau1:011:DAC CP NMS') - caput(pvioc+".B",ratio) - caput(pvioc+".CALC$","A*B") - -def MPA_Interlock(): - ioc="Kappa" + calcOut_pv = userCalcOut_clear(mda,n) + + caput(calcOut_pv+".DESC",desc) + caput(calcOut_pv+".INPA",DAC_pv+' CP NMS') + caput(calcOut_pv+".B",ratio) + caput(calcOut_pv+".CALC$","A*B") + +def mpa_interlock_mpa(): + """ + """ + desc = "MPA Interlock mpa" n=7 - pvioc="29id"+ioc+":userCalcOut"+str(n) - ClearCalcOut(ioc,n) - LLM=13.73 - HLM=23.73 - caput(pvioc+".DESC","MPA Interlock") - caput(pvioc+".INPA","29idKappa:m9.DRBV CP NMS") - caput(pvioc+".B",1) - caput(pvioc+".CALC$","ABS((("+str(LLM)+"<A && A<"+str(HLM)+") && (B>0))-1)") - caput(pvioc+".OCAL$",'A') - caput(pvioc+".OOPT",2) # When zero - caput(pvioc+".DOPT",0) # Use CALC - caput(pvioc+".IVOA",0) # Continue Normally - caput(pvioc+".OUT","29iddMPA:C0O PP NMS") + calcOut_pv = userCalcOut_clear(mda,n) + + caput(calcOut_pv+".DESC",desc) + tth_pv = Kappa_motor_dictionary('tth')[3] + caput(calcOut_pv+".INPA",tth_pv+".DRBV CP NMS") + caput(calcOut_pv+".B",1) + caput(calcOut_pv+".CALC$","ABS((("+str(tth_dLLM)+"<A && A<"+str(tth_dHLM)+") && (B>0))-1)") + caput(calcOut_pv+".OCAL$",'A') + caput(calcOut_pv+".OOPT",2) # When zero + caput(calcOut_pv+".DOPT",0) # Use CALC + caput(calcOut_pv+".IVOA",0) # Continue Normally + caput(calcOut_pv+".OUT",mpa_on_off_pv()+"PP NMS") -def MPA_Interlock_2(): - ioc="Kappa" +def mpa_interlock_DAC(): + """ + """ + desc = "MPA Interlock DAC" n=8 - pvioc="29id"+ioc+":userCalcOut"+str(n) - ClearCalcOut(ioc,n) - LLM=13.73 - HLM=23.73 - caput(pvioc+".DESC","MPA Interlock") - caput(pvioc+".INPA","29idKappa:m9.DRBV CP NMS") - caput(pvioc+".B",1) - caput(pvioc+".CALC$","ABS((("+str(LLM)+"<A && A<"+str(HLM)+") && (B>0))-1)") - caput(pvioc+".OCAL$",'A') - caput(pvioc+".OOPT",2) # When zero - caput(pvioc+".DOPT",0) # Use CALC - caput(pvioc+".IVOA",0) # Continue Normally - caput(pvioc+".OUT","29iddau1:dau1:011:DAC_Se PP NMS") -def Reset_MPA_HV(): + calcOut_pv = userCalcOut_clear(mda,n) + + caput(calcOut_pv+".DESC",desc) + tth_pv = Kappa_motor_dictionary('tth')[3] + caput(calcOut_pv+".INPA",tth_pv+".DRBV CP NMS") + caput(calcOut_pv+".B",1) + caput(calcOut_pv+".CALC$","ABS((("+str(tth_dLLM)+"<A && A<"+str(tth_dHLM)+") && (B>0))-1)") + caput(calcOut_pv+".OCAL$",'A') + caput(calcOut_pv+".OOPT",2) # When zero + caput(calcOut_pv+".DOPT",0) # Use CALC + caput(calcOut_pv+".IVOA",0) # Continue Normally + caput(calcOut_pv+".OUT",DAC_pv+"_Se PP NMS") + +def reset_mpa_HV(): """ resetting the SRS which controls the MPA HV Model: SRS PS350 diff --git a/instruments/remote_controlers.py b/instruments/remote_controlers.py index 60c3883d3e05cb5bd7dc68dc8621533b5d8eb97d..2c65239be40dcfcbbbc0a218203d49a0a2a08562 100644 --- a/instruments/remote_controlers.py +++ b/instruments/remote_controlers.py @@ -1,4 +1,4 @@ -from epics import * +from epics import caget,caput ############################################################################################################## ############################## RSXS Remote control ############################## @@ -337,7 +337,7 @@ def Ctrl_reset(Controller): CtrlButtonList.extend(['LSUpSeq','LSDownSeq','LSLeftSeq','LSRightSeq','L3Seq','RSUpSeq','RSDownSeq','RSLeftSeq','RSRightSeq','R3Seq']) for button in CtrlButtonList: for link in range(1,10): - Ctrl_but(Controller,button,link,PV,val) + Ctrl_button(Controller,button,link,PV,val) def Ctrl_button(Controller,button,link,PV,val):#writes to specified link (controller has 1 to 9) ctlpv=Controller+":ctl1:"+button diff --git a/instruments/scalers.py b/instruments/scalers.py new file mode 100644 index 0000000000000000000000000000000000000000..33da16e9605f0975a140f87140b866febd837e78 --- /dev/null +++ b/instruments/scalers.py @@ -0,0 +1,31 @@ +from math import floor + +from epics import caput,PV + +from .IEX_endstations import BL + +def scaler_cts(time_seconds=0.1,verbose=True): + """ + sets the scalers counting for the endstation defined in BL + """ + if BL.ioc == 'Kappa': + Kappa_scaler(time_seconds,verbose=verbose) + + +def Kappa_scaler(time_seconds=0.1,verbose=True): + """ + Sets the integration time for the scalers in the Kappa chamber + and mpa filter num if mpa is running + """ + scaler_pv="29idMZ0:scaler1.TP" + mpa_NumFilter = '29iddMPA:Proc1:NumFilter' + + caput(pv,time_seconds) + + pv=PV(mpa_NumFilter) + if pv.connected(): + caput(mpa_NumFilter,floor(time_seconds)) + + if verbose: + print("Integration time set to:", str(time_seconds)) + diff --git a/instruments/scanRecord.py b/instruments/scanRecord.py index a72e5d9bd9aa1e97302d7c1552bde9fb260bd86b..c2719c45e49a4d414620130d64f5be5ee89a28fe 100644 --- a/instruments/scanRecord.py +++ b/instruments/scanRecord.py @@ -32,17 +32,25 @@ class ScanRecord: used for short hand scanning and to get info related to a scanRecord """ - def __init__(self,scan_ioc,detector_dictionary,trigger_dictionary,before_scan_pv,after_scan_pv): + def __init__(self,scan_ioc,detector_dictionary,trigger_dictionary,before_scan_pv,after_scan_pv,**kwargs): """ scan_ioc: full pv for the ioc, "29idARPES:", "29idc:" detector_dictionary: dictionary corresponding to detector num and pv to proc => {det_num:'det_pv'} trigger_dictionary: dictionary corresponding to trigger num and trigger pv => {trigger_num:'trigger_pv'} before_scan_pv: pv to be proc'ed be for the start of a scan after_scan_pv: pv to be proc'ed be for the start of a scan + + **kwargs + reset: resets the scanRecord (True / False) => default = True + """ + kwargs.setdefault('reset',True) self.ioc = scan_ioc - self.reset_all(detector_dictionary,trigger_dictionary,before_scan_pv,after_scan_pv) + if kwargs['reset']: + self.reset_all(detector_dictionary,trigger_dictionary,before_scan_pv,after_scan_pv) + + pass ############################################################################################################## ################################ MDA (ScanRecord) files and folders ############################## diff --git a/instruments/scratch.py b/instruments/scratch.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/instruments/scratch.pyc b/instruments/scratch.pyc deleted file mode 100644 index 7b6343793f253325d6b81d2e85e2b85d7faa54bb..0000000000000000000000000000000000000000 Binary files a/instruments/scratch.pyc and /dev/null differ diff --git a/instruments/slits.py b/instruments/slits.py index 00b053e9ddb40c7df47d73105ecabf7f2b7d23f5..5a1ead3b31292e05bb4de2e8f775ef7b106d41ec 100644 --- a/instruments/slits.py +++ b/instruments/slits.py @@ -7,7 +7,7 @@ from .IEX_endstations import * from .shutters import main_shutter_close from .utilities import print_warning_message, read_dict from .VLS_PGM import mono_get_all -#from userStringSeq_userCalc import userStringSeq_clear, userStringSeq_pvs +from .encoders import encoders_reset slit_ioc="29idb:" @@ -165,6 +165,7 @@ def slits_scan_size(slit_name,direction,start,stop,step,**kwargs): center: slits center, if not specified then uses current center position """ kwargs.setdefault('center',slits_get(slit_name,verbose=False)[1]) + kwargs.setdefault('execute',True) slit_H,slit_V = slits_dictionary()[slit_name] @@ -176,7 +177,9 @@ def slits_scan_size(slit_name,direction,start,stop,step,**kwargs): #set slit center slits_set_center(slit_name,kwargs['center']) #scan - mda.fillin(size_rbv,size_val,start,stop,step,**kwargs) + BL.mda.fillin(size_rbv,size_val,start,stop,step,**kwargs) + if kwargs['execute']: + BL.mda.go(**kwargs) def slits_scan_center(slit_name,direction,start,stop,step,**kwargs): """ @@ -186,6 +189,7 @@ def slits_scan_center(slit_name,direction,start,stop,step,**kwargs): size: slits size, if not specified then uses current size """ kwargs.setdefault('size',slits_get(slit_name,verbose=False)[0]) + kwargs.setdefault('execute',True) slit_H,slit_V = slits_dictionary()[slit_name] @@ -197,7 +201,9 @@ def slits_scan_center(slit_name,direction,start,stop,step,**kwargs): #set slit center slits_set_size(slit_name,kwargs['size']) #scan - mda.fillin(center_rbv,center_val,start,stop,step,**kwargs) + BL.mda.fillin(center_rbv,center_val,start,stop,step,**kwargs) + if kwargs['execute']: + BL.mda.go(**kwargs) def slit1A_scribe_marks(): """ @@ -233,17 +239,14 @@ def slit1A_set(H_size,V_size,verbose=True,**kwargs): size = (H_size,V_size) center = kwargs['center'] slits_set(slit_name,size,center, verbose=verbose) - - - + def slit1A_get(verbose=True): """ - returns the current H_size,V_size,H_center,V_center + returns the current (H_size,V_size),(H_center,V_center) """ slit_name = "slit1A" - (H_size,V_size),(H_center,V_center) = slits_get(slit_name,verbose=verbose) - - return H_size,V_size,H_center,V_center + + return slits_get(slit_name,verbose=verbose) def slit2B_set(H_size,V_size,verbose=True,**kwargs): """ @@ -267,7 +270,6 @@ def slit2B_set(H_size,V_size,verbose=True,**kwargs): center = kwargs['center'] slits_set(slit_name,size,center, verbose=verbose) - def slit2B_set_small(Hsize,Vsize,coef,verbose=True,**kwargs): """ Used to scale the aperature size by coef @@ -278,16 +280,24 @@ def slit2B_set_small(Hsize,Vsize,coef,verbose=True,**kwargs): Vsize = Vsize * coef print_warning_message("closing Slit-2B down by a factor of", coef, "!!!") slit2B_set(Hsize,Vsize,verbose=True,**kwargs) - - + def slit2B_get(verbose=True): """ - returns the current H_size,V_size,H_center,V_center + returns the current (H_size,V_size),(H_center,V_center) """ slit_name = "slit2B" - (H_size,V_size),(H_center,V_center) = slits_get(slit_name,verbose=verbose) + return slits_get(slit_name,verbose=verbose) + +def slit2B_encoders_reset(Hcenter,Vcenter): + """ + Resetting Slit 2B encoders to 0 for a given position (Hcenter,Vcenter). + Slit size need to be set to 0. + + Previously: Reset_Slit2B_Encoders + """ + encoders_reset('slit2B',Hcenter,Vcenter) + slits_synch('slit2B') - return H_size,V_size,H_center,V_center def slit3C_set(size,verbose=True): """ @@ -345,8 +355,17 @@ def slit3D_get(verbose=True): return V_size,V_center +def slit3D_encoders_reset(Hcenter,Vcenter): + """ + Resetting Slit 2B encoders to 0 for a given position (Hcenter,Vcenter). + Slit size need to be set to 0. + + Previously: Reset_Slit2B_Encoders + """ + encoders_reset('slit3D',Hcenter,Vcenter) + slits_synch('slit3D') -def set_exit_slit(branch, size, verbose=True): +def exit_slit(branch, size, verbose=True): """ verbose used to supress printing diff --git a/instruments/staff.py b/instruments/staff.py index 7cecc2ba32e060e4a895a69af8b96d6c32b00a13..8ff6206d5d3e2609f6398ca0b24b73f169f56527 100644 --- a/instruments/staff.py +++ b/instruments/staff.py @@ -1,55 +1,7 @@ -from time import sleep -from epics import caget, caput -from files_and_folders import check_run,make_user_folders,folder_mda -from utilities import print_warning_message -from scanRecord import scanRecord_fillin -from userStringSeq_userCalc import userStringSeq_clear, userStringSeq_pvs,snake_scan_userCalcOut -from logfile import logfile_name_set,logfile_header -from current_amplifiers import ca_live_sequence -from slits import slit3C_get - -from EA import folder_EA - -global BL -staff_ioc = BL.ioc -folder = BL.folder -endstation_name = BL.endstation_name -file_prefix = BL.endstation_name - ############################################################################################################## -############################## setting folder ############################## +############################## staff detectors ############################## ############################################################################################################## -def folders_staff(user_name='Staff',**kwargs): - """ - Create and sets (if create_only=False) all the folders the current run and ARPES user - Sets the FileName for logging to be "UserName/YYYYMMDD_log.txt using logname_Set()" - - **kwargs: - set_folders = True (default); set the mda and EA scanRecords - = False; only makes the folders (was create_only) - run: run cycle e.g. 2022_1 (default => check_run() ) - ftp = True / False (default); print what needs to be added to the ftps crontab and create additional ftp folders - mda_ioc: will overwrite the default ioc for mda scans - debug - - """ - kwargs.setdefault('set_folders',True) - kwargs.setdefault('run',check_run()) - kwargs.setdefault('ftp',False) - kwargs.setdefault('debug',False) - - run = kwargs['run'] - - if kwargs['debug']: - print("run,folder,user_name,ioc,ftp: ",kwargs['run'],folder,user_name,ARPES_ioc,kwargs['ftp']) - - if endstation_name = 'ARPES': - folders_ARPES(user_name,**kwargs) - elif - endstation_name = 'Kappa' - folders_Kappa(user_name,**kwargs) - def staff_detector_dictionary(xrays=True): @@ -86,7 +38,7 @@ def staff_detector_dictionary(xrays=True): mono_details={ 68:"29idmono:ENERGY_SP", 69:"29idmonoMIR:P.RBV", - 70:,"29idmonoGRT:P.RBV" + 70:"29idmonoGRT:P.RBV" } det_dict.update(diodes) det_dict.update(slits_apertures) diff --git a/instruments/xrays.py b/instruments/xrays.py index 05e1c4090ede85918d78aef66caa7df5948e919b..105500f5bd5107c7b5ad13a9d88841fde711be06 100644 --- a/instruments/xrays.py +++ b/instruments/xrays.py @@ -5,26 +5,26 @@ functions related to using x-rays import numpy as np from time import sleep -from epics import caget,caput,PV -from .IEX_endstations import * - -from resolution import * -from IEX_VPU import * -from VLS_PGM import * -from slits import * -from shutters import * -from gate_valves import * -from diagnostics import * -from m3r import * -from logfile import * -from utilities import print_warning_message,make_table, take_closest_value -from mpa import * -from current_amplifiers import ca_average -from beamline import branch_cams_enable +from epics import caget,caput +from .IEX_endstations import BL + +from .resolution import * +from .IEX_VPU import * +from .VLS_PGM import * +from .slits import * +from .shutters import * +from .gate_valves import * +from .diagnostics import * +from .m3r import * +from .logfile import * +from .utilities import print_warning_message,make_table, take_closest_value +from .mpa import * +from .current_amplifiers import ca_average +from .beamline import branch_cams_enable from .ARPES import ARPES_mprint,ARPES_extra_pvs from .Kappa import Kappa_mprint -from electron_analyzer import getSESslit +from .electron_analyzer import getSESslit, EA ############################################################################################################## ############################## resets and detector lists ############################## ############################################################################################################## diff --git a/macros_and_scripts/ARPES_scripts b/macros_and_scripts/ARPES_macros.py similarity index 91% rename from macros_and_scripts/ARPES_scripts rename to macros_and_scripts/ARPES_macros.py index 89b9f23583785e14cd2ece4a8da99dc2e2bf5edf..240e6d80e466ef7ca34fc6bff6eae7cd8d249a51 100644 --- a/macros_and_scripts/ARPES_scripts +++ b/macros_and_scripts/ARPES_macros.py @@ -1,7 +1,14 @@ -from pytest import CaptureFixture -from sympy import capture +import numpy as np + from epics import caget,caput -from EA import scanEA + +from .ScanFunctions_plot import mda_1D,fit_gauss + +from ..instruments.electron_analyzer import scanEA +from ..instruments.slits import slit3C_set +from ..instruments.xrays import energy +from ..instruments.ARPES import mvth,scanx,mvx,mprint + ############################################################################################################## ############################## SES Work Function ############################## @@ -17,19 +24,19 @@ def WorkFunction_Measure(PE,KE=409,**kwargs): energy(500) #Fermi Level - slit(150) + slit3C_set(150) kwargs.update({'comment': 'EF1'}) EAlist=['KE',495,PE,frames,1] scanEA(EAlist,**kwargs) #Core level first order - slit(50) + slit3C_set(50) kwargs.update({'comment': 'KE1'}) EAlist=['KE',KE,PE,frames/10,1] scanEA(EAlist,**kwargs) #Core level second order - slit(150) + slit3C_set(150) kwargs.update({'comment': 'KE2'}) EAlist=['KE',KE+500,PE,frames*10,1] scanEA(EAlist,**kwargs) diff --git a/macros_and_scripts/BL_shutdown_macros.py b/macros_and_scripts/BL_shutdown.py similarity index 81% rename from macros_and_scripts/BL_shutdown_macros.py rename to macros_and_scripts/BL_shutdown.py index 12cf163802e048445a8ccd4f51c7e33273e6b634..800bf0c93902b720273eb0e63ef5d15fba729d02 100644 --- a/macros_and_scripts/BL_shutdown_macros.py +++ b/macros_and_scripts/BL_shutdown.py @@ -1,3 +1,8 @@ +from epics import caget,caput + +from ..instruments.electron_analyzer import EA +from ..instruments.shutters import main_shutter_close,branch_shutter_close +from ..instruments.diagnostics import diagnostics_all_out ############################################################################################################## ############################################ Shut down ################################################# @@ -6,7 +11,7 @@ def BL_Shutdown(): BL_CloseAllShutters() BL_Valve_All(state="CLOSE") - AllDiagOut() + diagnostics_all_out() try: EA.off() except: @@ -15,9 +20,9 @@ def BL_Shutdown(): caput("29iddau1:dau1:011:DAC_Set",0) #RSXS HV = "OFF" def BL_CloseAllShutters(): - Close_MainShutter() - Close_CShutter() - Close_DShutter() + main_shutter_close() + branch_shutter_close('c') + branch_shutter_close('d') def BL_Valve_All(state="CLOSE"): ValveList=["V1A","V2A","V3B","V4B","V5B","V6B","V7C","V8C","V9C","V10C","V7D","V8D","V9D","V10D"] diff --git a/instruments/Kappa_optimization.py b/macros_and_scripts/Kappa_optimization.py similarity index 95% rename from instruments/Kappa_optimization.py rename to macros_and_scripts/Kappa_optimization.py index 8e74eac13ead1c8c998e8cab9f2274e2b2d788ef..378f9c598983c35739c1894748dbd5275e9b1b80 100644 --- a/instruments/Kappa_optimization.py +++ b/macros_and_scripts/Kappa_optimization.py @@ -1,10 +1,10 @@ import matplotlib.pyplot as plt from epics import caget,caput -from .Kappa import * -from .Motors import * +from ..instruments.Kappa import * +from ..instruments.Motors import * -from IEX_plotting_and_analysis.IEX_plotting_and_analysis.ScanFunctions_plot import fit_mda, mda_1D +from .ScanFunctions_plot import fit_mda, mda_1D ##### Kappa Optimization scans ##### def Opt_d4(iteration,moveZ,graph='y',srs=None,start=-0.5,stop=0.5,step=0.04): diff --git a/macros_and_scripts/ScanFunctions_plot.py b/macros_and_scripts/ScanFunctions_plot.py new file mode 100755 index 0000000000000000000000000000000000000000..76a870d90fab3b1145b945b21220d61e0524eb5e --- /dev/null +++ b/macros_and_scripts/ScanFunctions_plot.py @@ -0,0 +1,2813 @@ +""" +#ScanFunctions_plot.py +how to copy tabs in stabs and not spaces jupyter + +For Fanny: Converting spaces to tabs from the terminal +cp ScanFunctions_IEX.py ScanFunctions_IEXbackup.py +sed -e 's/ /\t/g' ScanFunctions_IEXbackup.py > ScanFunctions_IEX.py +""" + +#### Other utilities: +import csv +from os import listdir +from os.path import join, isfile, dirname +from scipy.optimize import curve_fit +from scipy.special import erf +import numpy.polynomial.polynomial as poly +import ast + +### 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 netCDF4 import Dataset + + +##### APS / 29ID-IEX: +from ..mda import readMDA,scanDim +from IEX_plotting_and_analysis.IEX_nData import * + +try: + from epics import caget + from IEXcode.iexcode import BL_ioc + from IEXcode.iexcode.current_amplifiers import current2flux +except: + print("EPICS package and dependent functions are not installed") + +#from Macros_29id.ScanFunctions_IEX import ca2flux +#from Macros_29id.ScanFunctions_IEX import MDA_CurrentDirectory +#from Macros_29id.ScanFunctions_IEX import MDA_CurrentPrefix +#from Macros_29id.ScanFunctions_IEX import MDA_CurrentUser +#from Macros_29id.ScanFunctions_IEX import MDA_CurrentRun +#from Macros_29id.ScanFunctions_IEX import today +#from Macros_29id.ScanFunctions_IEX import read_dict +#from Macros_29id.ScanFunctions_IEX import LastMDA +#from Macros_29id.ScanFunctions_IEX import SetSlit_BL + + +########################################## + +if __name__=='__main__': + print(__file__) + + + + +############################################################################################################## +############################## JM Curves and Curve Fitting ############################## +############################################################################################################## + +def gauss(x, *p): + """ + Function for a guassian where p=[A,x0,sigma] + f(x)=A*numpy.exp(-(x-x0)**2/(2.*sigma**2) + fwhm=2.355*sigma + """ + A, x0, sigma = p + return A*np.exp(-(x-x0)**2/(2.*sigma**2)) + +def gauss_p0(y,x): + """ + Inital guesses for guassian fit + x and y are np.arrays + returns p0=[A,x0,sigma] + """ + A=max(y) + x0=x[np.where(y == max(y))][0] + sigma=0.2 + return [A,x0,sigma] + +def fit_gauss(x,y,xrange=None): + """ + x,y=EA_Spectrum(ScanNum, EnergyAxis,FilePath,Prefix) + x,y,x_name,y_name=mda_1D(ScanNum,DetectorNum) + + xrange = None to fit the full range + = [x1,x2] to fit a subrange + returns input_x,fit_y,coeff,var_matrix + where input_x and fit_y are the sub range x and the fitted data respectivley + coeff=[A,x0,sigma] + var_matrix is the fit variance + """ + if xrange is None: + input_y=y + input_x=x + else: + index1=np.where(x == x.flat[np.abs(x - xrange[0]).argmin()])[0][0] + index2=np.where(x == x.flat[np.abs(x - xrange[1]).argmin()])[0][0] + input_x=x[index1:index2] + input_y=y[index1:index2] + coeff, var_matrix = curve_fit(gauss, input_x, input_y, p0=gauss_p0(input_y,input_x)) + fit_y= gauss(input_x, *coeff) + return input_x,fit_y,coeff,var_matrix + + +############################################################################################################## +############################## Plot Tiff,JPEG,PNG ############################## +############################################################################################################## + + +# filepath='/home/beams/29IDUSER/Documents/User_Folders/Topp/S089.tif' +def plot_image(filepath,h=20,v=10,**kwargs): + """ + filepath = '/home/beams/29IDUSER/Documents/User_Folders/UserName/TifFile.tif' + ** kwargs are imshow kwargs: + cmap = colormap; examples => 'gray','BuPu','Inferno' + vmin,vmax, adjust max and min of colormap + """ + + image = mpimg.imread(filepath) + plt.figure(figsize=(h,v)) + plt.imshow(image,**kwargs) + plt.axis('off') + plt.show() + + + +def plot_image2(Filepath1,Filepath2,h=20,v=10): + """ + filepath = '/home/beams/29IDUSER/Documents/User_Folders/UserName/TifFile.tif' + """ + print(Filepath1) + print(Filepath2) + image1 = mpimg.imread(Filepath1) + image2 = mpimg.imread(Filepath2) + plt.figure(figsize=(h,v)) + plt.subplot(1,2,1), plt.imshow(image1,cmap='gray') + plt.axis('off') + plt.subplot(1,2,2), plt.imshow(image2,cmap='gray') + plt.axis('off') +# fig.subplots_adjust(wspace=0.5,hspace=0.5,left=0.125,right=0.9,top=0.85,bottom=0.15) + plt.tight_layout() + plt.show() + + +############################################################################################################## +############################## Extract mda Data ############################## +############################################################################################################## + +## mda_1D(1691,44,1,0,'/net/s29data/export/data_29idb/2018_1/mda_b')??? + + +def mda_unpack(ScanNum,filepath=None,prefix=None,scanIOC=None): + """ Return data file + dictionary D##:("pv",index##) + filepath: by default plot scans for the current data folder (as defined in BL_ioc() ScanRecord SaveData) + or specified folder path: + e.g. filepath='/net/s29data/export/data_29idb/2018_1/mda_b/' + prefix: by default, uses prefix as defined in ScanRecord + "mda_" for users, "Kappa_" or "ARPES_" for staff (sometimes) + """ + if scanIOC is None: + scanIOC = BL_ioc() + if filepath is None: + filepath =caget("29id"+scanIOC+":saveData_fileSystem",as_string=True)+caget("29id"+scanIOC+":saveData_subDir",as_string=True) + if filepath[1]=='/': + filepath="/net"+filepath[1:] + if filepath[-1] != '/': + filepath=filepath+'/' + if prefix is None: + prefix=caget("29id"+scanIOC+":saveData_baseName",as_string=True) + if prefix[-1] != '_': + prefix=prefix+'_' + mdaFile=filepath + prefix+'{:04}.mda'.format(ScanNum) + data_file = readMDA(mdaFile) + try: + D={} + n=len(data_file)-1 + for i in range(0,data_file[n].nd): + detector=data_file[n].d[i].fieldName + D[int(detector[1:])]=(data_file[n].d[i].name,i) + return (data_file,D) + except: + pass + +def mda_1D(ScanNum,DetectorNum,coeff=1,bckg=0,filepath=None,prefix=None,scanIOC=None): + """ Return x=positionner and y=detector(DetectorNum) + for a given detector number DYY (as shown in dview). """ + try: + (data_file,det)=mda_unpack(ScanNum,filepath,prefix,scanIOC) + index=det[DetectorNum][1] + x = data_file[1].p[0].data + y = data_file[1].d[index].data + x_name = data_file[1].p[0].name + y_name = data_file[1].d[index].name + if type(x_name) == bytes: + x_name=x_name.decode("utf-8") + if type(y_name) == bytes: + y_name=y_name.decode("utf-8") + n=list(zip(x,y)) + d=[n[i] for i, e in enumerate(n) if e != (0.0,0.0)] + if len(d)<len(n): + x=x[:len(d)] + y=y[:len(d)] + y=[(y[i]+bckg)*coeff for i, e in enumerate(y)] + #y=[(y[i]*coeff)+bckg for i, e in enumerate(y)] + return x,y,x_name,y_name + except: + print('error') + pass + + +def mda_1D_unscaled(ScanNum,DetectorNum,filepath=None,prefix=None,scanIOC=None): + """ Return x=positionner and y=detector(DetectorNum) + for a given detector number DYY (as shown in dview). """ + try: + (data_file,det)=mda_unpack(ScanNum,filepath,prefix,scanIOC) + if (data_file,det) == (None,None): + return(None) + else: + index=det[DetectorNum][1] + x = data_file[1].p[0].data + y = data_file[1].d[index].data + x_name = data_file[1].p[0].name + y_name = data_file[1].d[index].name + if type(x_name) == bytes: + x_name=x_name.decode("utf-8") + if type(y_name) == bytes: + y_name=y_name.decode("utf-8") + n=list(zip(x,y)) + d=[n[i] for i, e in enumerate(n) if e != (0.0,0.0)] + if len(d)<len(n): + x=x[:len(d)] + y=y[:len(d)] + bckg=min(y) + coeff=max(y)-min(y) + y=[(y[i]-bckg)/coeff for i, e in enumerate(y)] + return x,y,x_name,y_name + except: + pass + +def mda_1D_Xindex(ScanNum,DetectorNum,coeff=1,bckg=0,filepath=None,prefix=None,scanIOC=None): + """ Return x=index and y=detector(DetectorNum) + for a given detector number DYY (as shown in dview). """ + try: + (data_file,det)=mda_unpack(ScanNum,filepath,prefix,scanIOC) + index=det[DetectorNum][1] + x = data_file[1].d[0].data + y = data_file[1].d[index].data + x_name = data_file[1].d[0].name + y_name = data_file[1].d[index].name + if type(x_name) == bytes: + x_name=x_name.decode("utf-8") + if type(y_name) == bytes: + y_name=y_name.decode("utf-8") + n=list(zip(x,y)) + d=[n[i] for i, e in enumerate(n) if e != (0.0,0.0)] + if len(d)<len(n): + y=y[:len(d)] + x=list(range(1,len(y)+1)) + y=[(y[i]*coeff)+bckg for i, e in enumerate(y)] + return x,y,x_name,y_name + except: + pass + +def mda_1D_vsDet(ScanNum,DetectorNum,DetectorNum2,coeff=1,bckg=0,filepath=None,prefix=None,scanIOC=None): + """ Return x=index and y=detector(DetectorNum) + for a given detector number DYY (as shown in dview). """ + try: + #print(ScanNum,filepath,prefix,scanIOC) + (data_file,det)=mda_unpack(ScanNum,filepath,prefix,scanIOC) + index=det[DetectorNum][1] + index2=det[DetectorNum2][1] + x = data_file[1].d[0].data + x2 = data_file[1].d[index2].data + y = data_file[1].d[index].data + x_name = data_file[1].d[0].name + x2_name = data_file[1].d[index2].name + y_name = data_file[1].d[index].name + x = data_file[1].p[0].data + x2= data_file[1].d[index2].data + y= data_file[1].d[index].data + if type(x_name) == bytes: + x_name=x_name.decode("utf-8") + if type(y_name) == bytes: + y_name=y_name.decode("utf-8") + if type(x2_name) == bytes: + x2_name=x2_name.decode("utf-8") + n=list(zip(x,y)) + d=[n[i] for i, e in enumerate(n) if e != (0.0,0.0)] + if len(d)<len(n): + y=y[:len(d)] + x2=x2[:len(d)] + y=[(y[i]*coeff)+bckg for i, e in enumerate(y)] + return x2,y,x2_name,y_name + except: + pass + +def mda_Flux(ScanNum,DetectorNum,EnergyNum,filepath=None,prefix=None,scanIOC=None): + """ Return x=positionner and y=Flux(DetectorNum) + for a given diode recorded as detector number DYY (see ## in dview). + EnergyNum is the detector number for the mono RBV. + + """ + try: + (data_file,det)=mda_unpack(ScanNum,filepath,prefix,scanIOC) + index=det[DetectorNum][1] + Eindex=det[EnergyNum][1] + x = data_file[1].p[0].data + y = data_file[1].d[index].data + energy = data_file[1].d[Eindex].data + x_name = data_file[1].p[0].name + y_name = data_file[1].d[index].name + if type(x_name) == bytes: + x_name=x_name.decode("utf-8") + if type(y_name) == bytes: + y_name=y_name.decode("utf-8") + n=list(zip(x,y)) + d=[n[i] for i, e in enumerate(n) if e != (0.0,0.0)] + if len(d)<len(n): + x=x[:len(d)] + y=y[:len(d)] + y=[current2flux(y[i],energy[i],p=None) for (i, e) in enumerate(y)] + return x,y,x_name,y_name + except: + pass + + + +def mda_NormDet(ScanNum,DetectorNum,NormNum,coeff=1,bckg=0,filepath=None,prefix=None,scanIOC=None): + """ Return x=positionner and y=detector(DetectorNum) + for a given detector number DYY (as shown in dview). """ + try: + (data_file,det)=mda_unpack(ScanNum,filepath,prefix,scanIOC) + index=det[DetectorNum][1] + index_Norm=det[NormNum][1] + x = data_file[1].p[0].data + y= data_file[1].d[index].data + y_Norm=data_file[1].d[index_Norm].data + x_name = data_file[1].p[0].name + y_name = data_file[1].d[index].name#+"_norm:"+str(NormNum) + if type(x_name) == bytes: + x_name=x_name.decode("utf-8") + if type(y_name) == bytes: + y_name=y_name.decode("utf-8") + + n=list(zip(x,y)) + d=[n[i] for i, e in enumerate(n) if e != (0.0,0.0)] + if len(d)<len(n): + x=x[:len(d)] + y=y[:len(d)] + y=[y[i]/y_Norm[i] for i, e in enumerate(y)] + return x,y,x_name,y_name + except: + pass + +def mda_DivScan(ScanNum1,DetectorNum1,ScanNum2,DetectorNum2,coeff=1,bckg=0,filepath=None,prefix=None,scanIOC=None): + """ Return x=positionner and y=detector(DetectorNum) + for a given detector number DYY (as shown in dview). """ + try: + (data_file1,det1)=mda_unpack(ScanNum1,filepath,prefix,scanIOC) + index1=det1[DetectorNum1][1] + (data_file2,det2)=mda_unpack(ScanNum2,filepath,prefix,scanIOC) + index2=det2[DetectorNum2][1] + x1 = data_file1[1].p[0].data + y1= data_file1[1].d[index1].data + y2= data_file2[1].d[index2].data + x_name = data_file1[1].p[0].name + y_name = data_file1[1].d[index1].name+"_norm:"+str(ScanNum2) + if type(x_name) == bytes: + x_name=x_name.decode("utf-8") + if type(y_name) == bytes: + y_name=y_name.decode("utf-8") + + n=list(zip(x1,y1)) + d=[n[i] for i, e in enumerate(n) if e != (0.0,0.0)] + if len(d)<len(n): + x1=x1[:len(d)] + y1=y1[:len(d)] + y=[y1[i]/y2[i] for i, e in enumerate(y1)] + return x1,y,x_name,y_name + except: + pass + + + +def mda_2D(ScanNum,DetectorNum,filepath=None,prefix=None,scanIOC=None): + """ Return x=positionner and y=detector(DetectorNum) + for a given detector number DYY (as shown in dview). """ + try: + (data_file,det)=mda_unpack(ScanNum,filepath,prefix,scanIOC) + index=det[DetectorNum][1] + x_temp = data_file[2].p[0].data + y_temp = data_file[1].p[0].data + z_temp = data_file[2].d[index].data + x_name = data_file[2].p[0].name + y_name = data_file[1].p[0].name + z_name = data_file[2].d[index].name + if type(x_name) == bytes: + x_name=x_name.decode("utf-8") + if type(y_name) == bytes: + y_name=y_name.decode("utf-8") + if type(z_name) == bytes: + z_name=z_name.decode("utf-8") + + n=list(zip(x_temp,y_temp,z_temp)) + d=[n[i] for i, e in enumerate(n) if e != (0.0,0.0,0.0)] + if len(d)<len(n): + x_temp=x_temp[:len(d)] + y_temp=y_temp[:len(d)] + z_temp=z_temp[:len(d)] + x = x_temp[0] + y = y_temp + z = np.asarray(z_temp) #2-D array + return x,y,z,x_name,y_name,z_name + except: + pass + + +############################################################################################### +#################################### PLOT MDA ################################### +############################################################################################### + + + + +def plot_mda2D(ScanNum,DetectorNum,title=None,color=None,filepath=None,prefix=None): + try: + x,y,z,xName,yName,zName=mda_2D(ScanNum,DetectorNum,filepath,prefix) + fig, ax0 = plt.subplots() + if color is None: + color='gnuplot' + img = ax0.imshow(z, cmap=color, interpolation = 'nearest', extent = [min(x), max(x), max(y), min(y)], aspect = 'auto') + fig.colorbar(img) + if title is None: + plt.title(zName) + else: + plt.title(title) + ax0.set_xlabel(xName) + ax0.set_ylabel(yName) + # ax0.set_ylim(y.max(),y.min()) + plt.show() + except: + pass + + + +def plot_mda_series(*ScanDet,**kwArg): + """plot_mda_series(1217, 1226, 1, 39 ,0.025, **kwArg) + (first,last,countby,det,offset,**kwArg) + Optional data analysis keywords arguments: + Flux conversion (for diode only): flux= 3(User) or 25(Staff). + Norm option: norm = 'yes' normalizes all the scans to 1 (default: None) + NormDet= 1 for SR current, 14 for Mesh (D-branch); Normalize by the mesh does not work with norm='yes' + Optional graphical keywords arguments: + sizeH = 1,1.5,... increase horizontal figure size + sizeV = 1,1.5,... increase vertical figure size + marker = 'x','+','o','v','^','D',... (default:None) + markersize = 1,2,3,... (default: 5) + linewidth = 0.5,1,2... (default: 1) + linestyle = '-','--','-.',':' (default: solid '-') + color = 'r','b','m','c','g','y'... (default: jupyter colors series) + legend = 'best',Supper left', 'lower right'... (default: None) + log = 'log' (default: None = linear) + xrange = [x1,x2] (default: None = Autoscale) + yrange = [y1,y2] (default: None = Autoscale) + xlabel = 'mxLabel' (default: pv name) + ylabel = 'myLabel' (default: pv name) + ytickstyle = 'sci' for y axes (default: 'plain') + xtickstyle = 'sci' for y axes (default: 'plain') + filepath: by default plot scans for the current data folder (as defined in BL_ioc() ScanRecord SaveData) + or specified folder path: + 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_") + scanIOC: by default, uses the IOC for the current branch as define in BL_IOC() + """ + + if type(ScanDet[0]) is not tuple: + ScanDet=(tuple(ScanDet),) + m=1 + else: m= len(ScanDet) + + scanlist="" + j=0 + offset=0 + for n in range(m): + print(n) + print(m) + print(ScanDet) + det=ScanDet[n][3] + if len(ScanDet)>4 and isinstance(ScanDet[n][3],str)== False: + offset=ScanDet[n][4] + for scanNum in range(ScanDet[n][0],ScanDet[n][1]+ScanDet[n][2],ScanDet[n][2]): + scanlist+=str(scanNum)+',(det,1,'+str(offset)+'),' + j+=offset + cmd="plot_mda("+scanlist + if kwArg is not None: + for key, value in list(kwArg.items()): + if type(value) == str: + cmd=cmd+(key+'=\"'+value+'\",') + else: + cmd=cmd+(key+'='+str(value)+',') + if cmd[-1]==",": + cmd=cmd[:-1] + cmd=cmd+")" + if kwArg is not None: + for key, value in list(kwArg.items()): + if key=='q': + print('det=',det) + print(cmd) + exec(cmd) + + + +def plot_mda(*ScanDet,**kwArg): + + """ + Plot mda scans: *ScanDet = (scan,det,scan,det...),(scan,det,scan,det...),title=(subplot_title1,subplot_title2) + = subplot1, subplot2 + Optional data analysis keywords arguments: + Flux conversion (for diode only): flux= 3(D## for mono rbv, typically 3). + Norm option: norm = 'yes' normalizes all the scans to 1 (default: None) + NormDet = 1 for SR current, 14 for Mesh (D-branch); Normalize by the mesh does not work with norm='yes' + DivScan = ? + Optional graphical keywords arguments: + sizeH = 1,1.5,... increase horizontal figure size + sizeV = 1,1.5,... increase vertical figure size + marker = 'x','+','o','v','^','D',... (default:None) + markersize = 1,2,3,... (default: 5) + linewidth = 0.5,1,2... (default: 1) + linestyle = '-','--','-.',':' (default: solid '-') + color = 'r','b','m','c','g','y'... (default: jupyter colors series) + legend = 'best',Supper left', 'lower right'... (default: None) + log = 'log' (default: None = linear) + xrange = [x1,x2] (default: None = Autoscale) + yrange = [y1,y2] (default: None = Autoscale) + xlabel = 'mxLabel' (default: pv name) + ylabel = 'myLabel' (default: pv name) + ytickstyle = 'sci' for y axes (default: 'plain') + xtickstyle = 'sci' for y axes (default: 'plain') + filepath: by default plot scans for the current data folder (as defined in BL_ioc() ScanRecord SaveData) + or specified folder path: + 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_") + scanIOC: by default, uses the IOC for the current branch as define in BL_IOC() + """ + + args={ + 'marker':None, + 'markersize':5, + 'linewidth':1, + 'linestyle':'-', + 'color':None, + 'nticks':None, + 'sizeH':1, + 'sizeV':1, + 'title':'', + 'filepath':None, + 'prefix':None, + 'norm':None, + 'flux':None, + 'NormDet':None, + 'scanIOC':None, + 'legend':None, + 'vs_index':None, + 'vs_det':None, + 'xrange':[None,None], + 'yrange':[None,None], + 'save':True + } + + args.update(kwArg) + + mkr=args['marker'] + ms=args['markersize'] + lw=args['linewidth'] + ls=args['linestyle'] + c=args['color'] + path=args['filepath'] + prefix=args['prefix'] + scanIOC=args['scanIOC'] + save=args['save'] + + if 'legend' in args: + if args['legend'] == 'center left': + hsize=7 + + if type(ScanDet[0]) is not tuple: + ScanDet=(tuple(ScanDet),) + m=1 + else: m= len(ScanDet) + + def SubplotsLayout(m): + if m >1: + ncols=2 + else: + ncols=1 + nrows=max(sum(divmod(m,2)),1) + hsize=ncols*5*args['sizeH'] + vsize=nrows*4*args['sizeV'] + if nrows==1: vsize=nrows*3.5*args['sizeV'] + return nrows,ncols,hsize,vsize + + try: + nrows,ncols,hsize,vsize=SubplotsLayout(m) + + fig, axes = plt.subplots(nrows,ncols,figsize=(hsize,vsize)) # HxV + axes=np.array(axes) + + for (n,ax) in zip(list(range(m)),axes.flat): + for (i,j) in zip(ScanDet[n][0::2],ScanDet[n][1::2]): + if type(j) is tuple: + p,k,l=j + x,y,x_name,y_name=mda_1D(i,p,k,l,path,prefix) + elif args['flux'] is not None: + x,y,x_name,y_name=mda_Flux(i,j,args['flux'],path,prefix,scanIOC) + elif args['norm'] is not None: + x,y,x_name,y_name=mda_1D_unscaled(i,j,path,prefix,scanIOC) + elif args['NormDet'] is not None: + x,y,x_name,y_name=mda_NormDet(i,j,args['NormDet'],1,0,path,prefix,scanIOC) + elif args['vs_index'] is not None: + x,y,x_name,y_name=mda_1D_Xindex(i,j,1,0,path,prefix) + elif args['vs_det'] is not None: + x,y,x_name,y_name=mda_1D_vsDet(i,j,args['vs_det'],1,0,path,prefix) + #elif DivScan is not None: + # x,y,x_name,y_name=mda_DivScan(i,j,DivScan,DivDet,1,0,path,prefix,scanIOC) + else: + x,y,x_name,y_name=mda_1D(i,j,1,0,path,prefix,scanIOC) + ax.plot(x,y,label="mda_"+str(i),color=c,marker=mkr,markersize=ms,linewidth=lw,linestyle=ls) + ax.grid(color='lightgray', linestyle='-', linewidth=0.5) + + #modifying graph + if args['legend'] != None: + if args['legend'] == 'center left': + box = ax.get_position() + ax.set_position([box.x0, box.y0, box.width * 0.6, box.height]) + ax.legend(loc='center left', bbox_to_anchor=(1, 0.5)) + myleft=0.1 + myright=0.55 + else: + ax.legend(args['legend'], frameon=True) + if 'ytickstyle' in args: + ax.ticklabel_format(style=args['ytickstyle'], axis='y', scilimits=(0,0)) + if 'xtickstyle' in args: + ax.ticklabel_format(style=args['xtickstyle'], axis='x', scilimits=(0,0)) + if 'log' in args: + ax.set_yscale('log') + if args['xrange'] != [None,None]: + ax.set_xlim(args['xrange'][0],args['xrange'][1]) + if args['yrange'] != [None,None]: + ax.set_ylim(args['yrange'][0],args['yrange'][1]) + if 'xlabel' in args: + x_name=args['xlabel'] + if 'ylabel' in args: + y_name=args['ylabel'] + if args['nticks'] != None: + tck=args['nticks']-1 + ax.locator_params(tight=None,nbins=tck) + + + if 'title' in args: + mytitle=args['title'] + if type(mytitle) is not tuple: + ax.set(xlabel=x_name,ylabel=y_name,title=mytitle) + else: + p=len(mytitle) + if n == p: + ax.set(xlabel=x_name,ylabel=y_name,title='') + else: + ax.set(xlabel=x_name,ylabel=y_name,title=mytitle[n]) + # ax.text(0.5, 1.025,mytitle,horizontalalignment='center',fontsize=14,transform = ax.transAxes) + ax.grid(color='lightgray', linestyle='-', linewidth=0.5) + + if ncols==1 and nrows==1 and kwArg.get('legend')!='center left': + fig.subplots_adjust(wspace=0.5,hspace=0.5,left=0.25,right=0.88,top=0.85,bottom=0.22) + elif ncols==1 and kwArg.get('legend')=='center left': + fig.subplots_adjust(wspace=0.5,hspace=0.5,left=myleft,right=myright,top=0.85,bottom=0.22) + else: + fig.subplots_adjust(wspace=0.5,hspace=0.5,left=0.125,right=0.9,top=0.85,bottom=0.15) + + plt.tight_layout() + if save: + try: + fname=join('/home/beams/29IDUSER/Documents/User_Folders/','lastfigure.png') + print(fname) + plt.savefig(fname) + except: + pass + plt.show() + except: + pass + + + +def plot_mda_lists(*ScanDet,**kwArg): + """ + Plot mda scans: *ScanDet = (scanNum_list,detNum_list),(scanNum_list,detNum_list) + = subplot1, subplot2 + Optional data analysis keywords arguments: + Flux conversion (for diode only): flux= 3(User) or 25(Staff). + Norm option: norm = 'yes' normalizes all the scans to 1 (default: None) + NormDet= 1 for SR current, 14 for Mesh (D-branch); Normalize by the mesh does not work with norm='yes' + Optional graphical keywords argudef plot_mdaments: + sizeH = 1,1.5,... increase horizontal figure size + sizeV = 1,1.5,... increase vertical figure size + marker = 'x','+','o','v','^','D',... (default:None) + markersize = 1,2,3,... (default: 5) + linewidth = 0.5,1,2... (default: 1) + linestyle = '-','--','-.',':' (default: solid '-') + color = 'r','b','m','c','g','y'... (default: jupyter colors F) + legend = 'best',Supper left', 'lower right'... (default: None) + log = 'log' (default: None = linear) + xrange = [x1,x2] (default: None = Autoscale) + yrange = [y1,y2] (default: None = Autoscale) + xlabel = 'mxLabel' (default: pv name) + ylabel = 'myLabel' (default: pv name) + ytickstyle = 'sci' for y axes (default: 'plain') + xtickstyle = 'sci' for y axes (default: 'plain') + filepath: by default plot scans for the current data folder (as defined in BL_ioc() ScanRecord SaveData) + or specified folder path: + 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_") + scanIOC: by default, uses the IOC for the current branch as define in BL_IOC() + """ + + args={ + 'marker':None, + 'markersize':5, + 'linewidth':1, + 'linestyle':'-', + 'color':None, + 'nticks':None, + 'sizeH':1, + 'sizeV':1, + 'title':'', + 'filepath':None, + 'prefix':None, + 'norm':None, + 'flux':None, + 'NormDet':None, + 'scanIOC':None, + 'legend':None, + 'vs_index':None, + 'xrange':[None,None], + 'yrange':[None,None] + } + + args.update(kwArg) + + mkr=args['marker'] + ms=args['markersize'] + lw=args['linewidth'] + ls=args['linestyle'] + c=args['color'] + path=args['filepath'] + prefix=args['prefix'] + scanIOC=args['scanIOC'] + + + + if 'legend' in args: + if args['legend'] == 'center left': + hsize=7 + + #setting up the subplot + if type(ScanDet[0]) is not tuple: + ScanDet=(tuple(ScanDet),) + m=1 + else: m= len(ScanDet) + + def SubplotsLayout(m): + if m >1: + ncols=2 + else: + ncols=1 + nrows=max(sum(divmod(m,2)),1) + hsize=ncols*5*args['sizeH'] + vsize=nrows*4*args['sizeV'] + if nrows==1: vsize=nrows*3.5*args['sizeV'] + return nrows,ncols,hsize,vsize + + try: + nrows,ncols,hsize,vsize=SubplotsLayout(m) + fig, axes = plt.subplots(nrows,ncols,figsize=(hsize,vsize)) # HxV + axes=np.array(axes) + + + for (n,ax) in zip(list(range(m)),axes.flat): #n=subplot tuple + scanNum_list=ScanDet[n][0] + detNum_list=ScanDet[n][1] + + if type(scanNum_list) is int: + scanNum_list=[scanNum_list] + if type(detNum_list) is int: + detNum_list=[detNum_list] + for i in range(1,len(scanNum_list)): + detNum_list.append(detNum_list[0]) + if type(args['filepath']) is not list: + filepath_list=[args['filepath']] + for i in range(1,len(scanNum_list)): + filepath_list.append(filepath_list[0]) + else: filepath_list=args['filepath'] + if type(args['prefix']) is not list: + prefix_list=[args['prefix']] + for i in range(1,len(scanNum_list)): + prefix_list.append(prefix_list[0]) + else: prefix_list=args['prefix'] + if type(args['scanIOC']) is not list: + scanIOC_list=[args['scanIOC']] + for i in range(1,len(scanNum_list)): + scanIOC_list.append(scanIOC_list[0]) + else: scanIOC_list=args['scanIOC'] + #loading the data + for index in range(0,len(scanNum_list)): + i=scanNum_list[index] + j=detNum_list[index] + path=filepath_list[index] + prefix=prefix_list[index] + scanIOC=scanIOC_list[index] + #print(i) + if type(j) is tuple: + p,k,l=j + x,y,x_name,y_name=mda_1D(i,p,k,l,path,prefix) + elif args['flux'] is not None: + x,y,x_name,y_name=mda_Flux(i,j,args['flux'],path,prefix,scanIOC) + elif args['norm'] is not None: + x,y,x_name,y_name=mda_1D_unscaled(i,j,path,prefix,scanIOC) + elif args['NormDet'] is not None: + x,y,x_name,y_name=mda_NormDet(i,j, args['NormDet'],1,0,path,prefix,scanIOC) + else: + x,y,x_name,y_name=mda_1D(i,j,1,0,path,prefix,scanIOC) + #adding to graph + ax.grid(color='lightgray', linestyle='-', linewidth=0.5) + ax.plot(x,y,label="mda_"+str(i),color=c,marker=mkr,markersize=ms,linewidth=lw,linestyle=ls) + + #modifying graph + if args['legend'] != None: + if args['legend'] == 'center left': + box = ax.get_position() + ax.set_position([box.x0, box.y0, box.width * 0.6, box.height]) + ax.legend(loc='center left', bbox_to_anchor=(1, 0.5)) + myleft=0.1 + myright=0.55 + else: + ax.legend(args['legend'], frameon=True) + if 'ytickstyle' in args: + ax.ticklabel_format(style=args['ytickstyle'], axis='y', scilimits=(0,0)) + if 'xtickstyle' in args: + ax.ticklabel_format(style=args['xtickstyle'], axis='x', scilimits=(0,0)) + if 'log' in args: + ax.set_yscale('log') + if args['xrange'] != [None,None]: + ax.set_xlim(args['xrange'][0],args['xrange'][1]) + if args['yrange'] != [None,None]: + ax.set_ylim(args['yrange'][0],args['yrange'][1]) + if 'xlabel' in args: + x_name=args['xlabel'] + if 'ylabel' in args: + y_name=args['ylabel'] + if args['nticks'] != None: + tck=args['nticks']-1 + ax.locator_params(tight=None,nbins=tck) + + if 'title' in args: + if type(args['title']) is not str: + mytitle=args['title'][n] + else: + mytitle=args['title'] + ax.set(xlabel=x_name,ylabel=y_name,title=mytitle) + #adjusting subplots + if ncols==1 and nrows==1 and kwArg.get('legend')!='center left': + fig.subplots_adjust(wspace=0.5,hspace=0.5,left=0.25,right=0.88,top=0.85,bottom=0.22) + elif ncols==1 and kwArg.get('legend')=='center left': + fig.subplots_adjust(wspace=0.5,hspace=0.5,left=myleft,right=myright,top=0.85,bottom=0.22) + else: + fig.subplots_adjust(wspace=0.5,hspace=0.5,left=0.125,right=0.9,top=0.85,bottom=0.15) + #show plot + plt.tight_layout() + plt.show() + + except: + pass + + + + +############################################################################################### +#################################### PLOT netCDF ################################### +############################################################################################### + + + + +def nc_unpack(ScanNum,FilePath=None,Prefix=None): + """ + Returns the full netCDF data file + meta data (Attributes/Exta PVs) + c.variables['Attr_EnergyStep_Swept'][:][0] + data array is accessed + nc.variables['array_data'][:][0] + + FilePath: by default plot scans for the current data folder (as shown on detector panel) + or specified folder path ending with '/': + e.g. user : FilePath='/net/s29data/export/data_29idc/2018_2/UserName/netCDF/' + e.g. staff: FilePath='/net/s29data/export/data_29idb/2018_2/netCDF/' + Prefix: by default, uses prefix as shown on detector panel ("EA_") + """ + def GetFileName(): + SubFolder= caget('29idcEA:netCDF1:FilePath',as_string=True) + if SubFolder[0]=='X': drive='b' + elif SubFolder[0]=='Y': drive='c' + FilePath='/net/s29data/export/data_29id'+drive+SubFolder[2:]+'/' + Prefix = caget("29idcEA:netCDF1:FileName_RBV",as_string=True) + return FilePath, Prefix + + if FilePath is None: + FilePath=GetFileName()[0] + if Prefix is None: + Prefix= GetFileName()[1] + myFile=FilePath+Prefix+'{:04}.nc'.format(ScanNum) + nc = Dataset(myFile,mode='r') + return nc + +def EA_data(nc): + """ Returns: x,xname,ycrop,yname,img,ActualPhotonEnergy,WorkFunction,PE + """ + + LowEnergy=nc.variables['Attr_LowEnergy'][:][0] + HighEnergy=nc.variables['Attr_HighEnergy'][:][0] + ActualPhotonEnergy=nc.variables['Attr_ActualPhotonEnergy'][:][0] + EnergyStep_Swept=nc.variables['Attr_EnergyStep_Swept'][:][0] + EnergyStep_Swept_RBV=nc.variables['Attr_EnergyStep_Swept_RBV'][:][0] + EperChannel=nc.variables['Attr_EnergyStep_Fixed_RBV'][:][0] + GratingPitch=nc.variables['Attr_GratingPitch'][:][0] + MirrorPitch=nc.variables['Attr_MirrorPitch'][:][0] + + WorkFunction=nc.variables['Attr_Energy Offset'][:][0] + + DetMode=nc.variables['Attr_DetectorMode'][:][0] # BE=0,KE=1 + AcqMode= nc.variables['Attr_AcquisitionMode'][:][0] # Swept=0, Fixed=1, BS=2 + LensMode=nc.variables['Attr_LensMode'][:][0] + + PassEnergyMode=nc.variables['Attr_PassEnergy'][:][0] + PEdict={0:1,1:2,2:5,3:10,4:20,5:50,6:100,7:200,8:500} + PE=PassEnergyMode + + #ActualPhotonEnergy,WorkFunction,PE=EA_metadata(nc)[0:3] + data = nc.variables['array_data'][:][0] + + def SelectValue(which,x1,x2): + if which == 0: value=x1 + if which == 1: value=x2 + return value + + ### Energy Scaling: + Edelta = SelectValue(DetMode,-EnergyStep_Swept,EnergyStep_Swept) + if AcqMode == 0: # Swept + Ehv=ActualPhotonEnergy + Estart = SelectValue(DetMode, Ehv-LowEnergy, LowEnergy) + #Estop = SelectValue(DetMode, Ehv-HighEnergy, HighEnergy) + if AcqMode >= 1: # Fixed or Baby Swept + Ecenter=nc.variables['Attr_CentreEnergy_RBV'][:][0] + #print nc.variables#JM was here + #print Ecenter,Edelta#JM was here + Estart=Ecenter-(data.shape[1]/2.0)*Edelta + Eunits=SelectValue(DetMode,"Binding Energy (eV)","Kinetic Energy (eV)") + + x=[Estart+Edelta*i for i,e in enumerate(data[0,:])] + xname=Eunits + + ### Angular Scaling: + if LensMode>-1: # Angular Modes RE changed from >0 (Angular) to >-1 (all mode) + CenterChannel=571 + FirstChannel=0 + Ddelta =0.0292717 + Dstart = (FirstChannel-CenterChannel)*Ddelta + y=[Dstart+Ddelta*i for i,e in enumerate(data[:,0])] + #getting rid of edges with no data + data=nc.variables['array_data'] + #x1=338;x2=819 #old + x1=338-100;x2=819-10 + datacrop=data[:,x1:x2] + ycrop=y[x1:x2] + yname='Degrees' + else: + ycrop,yname=None,'mm' + return x,xname,ycrop,yname,datacrop,ActualPhotonEnergy,WorkFunction,PE + + + + +def EA_Image(ScanNum,EnergyAxis='KE',FilePath=None,Prefix=None): + """ + Returns + x = KE or BE energy scale; BE is calculated based on the wk in the SES and the mono energy + y = Integrated intensity + + FilePath: by default plot scans for the current data folder (as shown on detector panel) + or specified folder path ending with '/': + e.g. user : FilePath='/net/s29data/export/data_29idc/2018_2/UserName/netCDF/' + e.g. staff: FilePath='/net/s29data/export/data_29idb/2018_2/netCDF/' + Prefix: by default, uses prefix as shown on detector panel ("EA_") + + x,y,img=EA_Image(1) + plt.imshow(img,extent = [min(x), max(x), min(y), max(y)], aspect = 'auto') + plt.show()) + """ + nc=nc_unpack(ScanNum,FilePath,Prefix) + x,xname,y,yname,img,hv,wk,PE=EA_data(nc) + y=np.array(y) + img=img[0] + if EnergyAxis == 'KE': + x=np.array(x) + else: + x=hv-wk-np.array(x) + return x, y, img + +def EA_Spectrum(ScanNum,EnergyAxis='KE',FilePath=None,Prefix=None): + """ + Returns + x = KE or BE energy scale; BE is calculated based on the wk in the SES and the mono energy + y = Integrated intensity + FilePath: by default plot scans for the current data folder (as shown on detector panel) + or specified folder path ending with '/': + e.g. user : FilePath='/net/s29data/export/data_29idc/2018_2/UserName/netCDF/' + e.g. staff: FilePath='/net/s29data/export/data_29idb/2018_2/netCDF/' + Prefix: by default, uses prefix as shown on detector panel ("EA_") + + Simple plot: x,y=EA_Spectrum(ScanNum);plt.plot(x,y);plt.xlim(min(x),xmax(x));plt.show() +""" + x, ang, img = EA_Image(ScanNum, EnergyAxis,FilePath,Prefix) + y = np.asarray([sum(img[:,i]) for i in range(img.shape[1])]) + return x, y + +def EA_metadata(ScanNum,FilePath=None,Prefix=None): + """ Returns: ActualPhotonEnergy,WorkFunction,GratingPitch,MirrorPitch + """ + nc=nc_unpack(ScanNum,FilePath,Prefix) + # SES parameters + LowEnergy=nc.variables['Attr_LowEnergy'][:][0] + HighEnergy=nc.variables['Attr_HighEnergy'][:][0] + EnergyStep_Swept=nc.variables['Attr_EnergyStep_Swept'][:][0] + EnergyStep_Swept_RBV=nc.variables['Attr_EnergyStep_Swept_RBV'][:][0] + EperChannel=nc.variables['Attr_EnergyStep_Fixed_RBV'][:][0] + WorkFunction=nc.variables['Attr_Energy Offset'][:][0] + DetMode=nc.variables['Attr_DetectorMode'][:][0] # BE=0,KE=1 + AcqMode= nc.variables['Attr_AcquisitionMode'][:][0] # Swept=0, Fixed=1, BS=2 + LensMode=nc.variables['Attr_LensMode'][:][0] + PassEnergyMode=nc.variables['Attr_PassEnergy'][:][0] + PEdict={0:1,1:2,2:5,3:10,4:20,5:50,6:100,7:200,8:500} + PE=PassEnergyMode + + TEY=nc.variables['Attr_TEY'][:][0] + + # Mono parameters + ActualPhotonEnergy=nc.variables['Attr_ActualPhotonEnergy'][:][0] + GratingPitch=nc.variables['Attr_GratingPitch'][:][0] + MirrorPitch=nc.variables['Attr_MirrorPitch'][:][0] + Grating_Density=nc.variables['Attr_Grating_Density'][:][0] + Grating_Slot=nc.variables['Attr_Grating_Slot'][:][0] + GRT_Offset_1=nc.variables['Attr_GRT_Offset_1'][:][0] + GRT_Offset_2=nc.variables['Attr_GRT_Offset_2'][:][0] + GRT_Offset_3=nc.variables['Attr_GRT_Offset_3'][:][0] + MIR_Offset_1=nc.variables['Attr_MIR_Offset_1'][:][0] + b2_GRT1=nc.variables['Attr_b2-GRT1'][:][0] + b2_GRT2=nc.variables['Attr_b2-GRT2'][:][0] + b2_GRT3=nc.variables['Attr_b2-GRT3'][:][0] + + offset=[MIR_Offset_1,GRT_Offset_1,GRT_Offset_2,GRT_Offset_3] + b2=[0,b2_GRT1,b2_GRT2,b2_GRT3] + + return WorkFunction,ActualPhotonEnergy,MirrorPitch,GratingPitch,Grating_Density,Grating_Slot,offset,b2 + + +def Get_EDCmax(ScanNum,EnergyAxis='KE',FilePath=None,Prefix=None): + x,y=EA_Spectrum(ScanNum, EnergyAxis,FilePath,Prefix) + maxY= max(y) + maxX=round(x[np.where(y == max(y))][0],3) + return maxX,maxY # energy position, intensity of the peak + + + +def EDC_Series(first,last,countby, EnergyAxis='BE',title="",norm=None,FilePath=None,Prefix=None): + """ + Plots a seriew of EA_Spectrum + """ + if title == "": + title="Scans: "+str(first)+"/"+str(last)+"/"+str(countby) + fig = plt.figure(figsize=(6,6)) + a1 = fig.add_axes([0,0,1,1]) + for ScanNum in range(first,last+countby,countby): + x,y=EA_Spectrum(ScanNum, EnergyAxis,FilePath,Prefix) + if norm is not None: maxvalue=max(y) + else: maxvalue=1 + plt.plot(x,y/maxvalue,label='#'+str(ScanNum)) + plt.legend(ncol=2, shadow=True, title=title, fancybox=True) + plt.grid(color='lightgray', linestyle='-', linewidth=0.5) + a1.plot + if EnergyAxis == 'BE': + a1.set_xlim(max(x),min(x)) + plt.show() + + + + +def plot_nc(*ScanNum,**kwgraph): + """ + ScanNum = Scan number to be plotted: single scan, or range (first,last,countby) to average. + kwgraph = EDC / FilePath / Prefix + - Transmission mode: angle integrated EDC. + - Angular mode: + default: band map only + EDC = 'y' : angle integrated EDC only + EDC = 'both': angle integrated EDC + band map + EnergyAxis = KE (default) or BE (BE uses work function from SES) + FilePath: by default plot scans for the current data folder (as shown on detector panel) + or specified folder path ending with '/': + e.g. user : FilePath='/net/s29data/export/data_29idc/2018_2/UserName/netCDF/' + e.g. staff: FilePath='/net/s29data/export/data_29idb/2018_2/netCDF/' + Prefix: by default, uses prefix as shown on detector panel ("EA_") + + """ + FilePath,Prefix,EDC,EnergyAxis,avg=None,None,None,'KE',None + if kwgraph is not None: + for key, value in list(kwgraph.items()): + if key=='FilePath': FilePath=value + if key=='Prefix': Prefix=value + if key=='EDC': EDC=value + if key=='EnergyAxis': EnergyAxis=value + if key=='avg': avg=1 + #Get lens mode + nc=nc_unpack(ScanNum[0],FilePath,Prefix) + LensMode=nc.variables['Attr_LensMode'][:][0] + #Loading Scans () + first=ScanNum[0] + if len(ScanNum)==1: + last =ScanNum[0] + countby=1 + else: + last=ScanNum[1] + countby=ScanNum[2] + for n in range(first,last+countby,countby): + x,intensity=EA_Spectrum(n,EnergyAxis,FilePath,Prefix) + x,y,img =EA_Image(n,EnergyAxis,FilePath,Prefix) + if n == first: + Spectra=intensity + Img=img + else: + if avg == 1: #Summing the Scans + print('averaging') + Spectra=np.add(Spectra, intensity) + Img=np.add(Img,img) + + #Getting plot size + if LensMode == 0 or EDC != None and EDC != 'both': #Integrated Angle only + hsize,vsize=6,3.5 + elif LensMode >0 and EDC == None: + hsize,vsize=6,4 + elif LensMode >0 and EDC == 'both': + hsize,vsize=6,8 + if kwgraph is not None: + for key, value in list(kwgraph.items()): + if key=='hsize': hsize=value + if key=='vsize': vsize=value + #plotting\ + if LensMode == 0 or EDC != None and EDC != 'both': #Integrated Angle only + #print('p-DOS only') + fig, ax = plt.subplots(figsize=(hsize,vsize)) # HxV + ax.plot(x,Spectra) + if EnergyAxis == "BE": + ax.set_xlim(max(x),min(x)) + else: + ax.set_xlim(min(x),max(x)) + ax.set(xlabel=EnergyAxis,ylabel='Intensity') + ax.ticklabel_format(style='sci', axis='y', scilimits=(0,0)) + ax.grid(color='lightgray', linestyle='-', linewidth=0.5) + elif LensMode >0 and EDC is None: #Imgage Only + #print('Image Only') + fig, ax = plt.subplots(figsize=(hsize,vsize)) # HxV + if EnergyAxis == 'BE': + fig=ax.imshow(Img,extent = [max(x), min(x), min(y), max(y)], aspect = 'auto') + else: + fig=ax.imshow(Img,extent = [min(x), max(x), min(y), max(y)], aspect = 'auto') + ax.set(xlabel=EnergyAxis,ylabel="Angle") + elif LensMode >0 and EDC == 'both': + #print('both') + fig, axes = plt.subplots(2,1,figsize=(hsize,vsize)) # HxV + axes=np.array(axes) + for (n,ax) in zip(list(range(2)),axes.flat): + if n == 0: + ax.ticklabel_format(style='sci', axis='y', scilimits=(0,0)) + ax.grid(color='lightgray', linestyle='-', linewidth=0.5) + ax.plot(x,Spectra) + if EnergyAxis == "BE": + ax.set_xlim(max(x),min(x)) + else: + ax.set_xlim(min(x),max(x)) + ax.set(xlabel=EnergyAxis,ylabel='Intensity') + if n == 1: + if EnergyAxis == 'BE': + ax.imshow(Img,extent = [max(x), min(x), min(y), max(y)], aspect = 'auto') + else: + ax.imshow(Img,extent = [min(x), max(x), min(y), max(y)], aspect = 'auto') + ax.set(xlabel=EnergyAxis,ylabel='Angle') + plt.tight_layout() + plt.show() + + +def plot_nc_Sum(first,last,**kwgraph): + + FilePath,Prefix=None,None + if kwgraph is not None: + for key, value in list(kwgraph.items()): + if key=='FilePath': FilePath=value + if key=='Prefix': Prefix=value + for n in range(first,last+1): + print(n) + nc=nc_unpack(n,FilePath,Prefix) + x,xname,ycrop,yname,img,hv,wk,PE=EA_data(nc) + LensMode=nc.variables['Attr_LensMode'][:][0] + if n == first: + datasum = nc.variables['array_data'] + x,xname,ycrop,yname,img,hv,wk,PE=EA_data(nc) + else: + data = nc.variables['array_data'] + tmp=datasum + datasum=np.add(tmp,data) + crop_data=data[:,338:819] + fig, ax = plt.subplots(figsize=(6,4)) # HxV + fig=ax.imshow(crop_data.squeeze(),extent = [min(x), max(x), min(ycrop), max(ycrop)], aspect = 'auto') + plt.show() + + + + + + + + + + + +############################################################################################### +##################################### FR curves fitting ####################################### +############################################################################################### + + +def fit_mda(scannum,det,FWHM_or_PolyOrder,fct,hkl_positionner=False,xrange=None,title='',marker='x',graph=True, filepath=None,prefix=None,scanIOC=None): + """ + fct= 'gauss','lorz','erf','poly','box' + hkl_positionner = 'H','K','L','tth','th','chi','phi' + """ + + if hkl_positionner == False: + x,y,x_name,y_name=mda_1D(scannum,det,1,0,filepath,prefix,scanIOC) + if hkl_positionner: + d={'h':46,'k':47,'l':48,'tth':54,'th':55,'chi':56,'phi':57} + x,y,x_name,y_name=mda_1D_vsDet(scannum,det,d[hkl_positionner.lower()],1,0,filepath,prefix,scanIOC) + + if scanIOC is None: + scanIOC = BL_ioc() + + if scanIOC == 'Kappa' and fct != 'poly': + try: + title=title + ' centroid = '+str(centroid_avg(scannum)) + except: + pass + + def closest(lst, K): + return lst[min(range(len(lst)), key = lambda i: abs(lst[i]-K))] + + def gaussian(x,*p): + amp, cen, wid, bkgd = p + return bkgd+amp*np.exp(-np.power(x - cen, 2.) / (2 * np.power(wid, 2.))) + + def lorentzian( x, *p): + amp, x0, gam, bkgd =p + return bkgd+amp * gam**2 / ( gam**2 + ( x - x0 )**2) + + def step(z,amp=1,bkgd=0,z0=0,width=1): + return (amp*erf((z-z0)/width))+bkgd + + def box(x, *p): + height, center, width ,bkgd = p + return bkgd+height*(center-width/2 < x)*(x < center+width/2) + + + + if xrange is not None: + x1=closest(x,xrange[0]) + x2=closest(x,xrange[1]) + xrange=[x.index(x1),x.index(x2)] + xmin=min(xrange) + xmax=max(xrange) + xcrop=x[xmin:xmax] + ycrop=y[xmin:xmax] + xdata = np.array(xcrop) + ydata = np.array(ycrop) + else: + xdata = np.array(x) + ydata = np.array(y) + + + Imax=np.max(ydata) + #print(xdata) + #print(ydata) + x0=xdata[np.where(ydata==Imax)][0] + A0=xdata[0] + + nPt_fit=200 + xfit = np.linspace(min(x),max(x), nPt_fit) + + + if fct == 'gauss': + FWHM=FWHM_or_PolyOrder + best_vals, covar = curve_fit(gaussian, xdata, ydata, p0=[Imax, x0, FWHM, A0]) #5 p0=[amp,cen,wid] + yfit=gaussian(xfit,*best_vals) + FWHM=2.355*best_vals[2] + center=best_vals[1] + print('Amplitude: ',best_vals[0]) + elif fct == 'lorz': + FWHM=FWHM_or_PolyOrder + best_vals, covar = curve_fit(lorentzian, xdata, ydata, p0=[Imax, x0, FWHM, A0]) #5 p0=[amp,cen,wid] + yfit=lorentzian(xfit,*best_vals) + FWHM=2.355*best_vals[2] + center=best_vals[1] + print('Amplitude: ',best_vals[0]) + elif fct == 'erf' or fct == 'box': + FWHM=FWHM_or_PolyOrder + xmax=np.max(xdata) + xmin=np.min(xdata) + amp=np.mean(ydata) + x0=np.mean(xdata) + ymin=np.min(ydata) + if fct == 'erf': + yfirst=ydata[np.where(xdata == xmin)][0] + ylast =ydata[np.where(xdata == xmax)][0] + if yfirst-ylast >0: amp=-abs(amp) #amp <0 step down + else: amp = abs(amp) #amp >0 step up + p0=[amp, ymin, x0, FWHM] + popt,pcor = curve_fit(step, xdata, ydata, p0=p0) + yfit=step(xfit,*popt) + FWHM=popt[3] + center=popt[2] + elif fct == 'box': + p0=[amp, x0, FWHM, A0] + popt,pcor = curve_fit(box, xdata, ydata, p0=p0) + yfit=box(xfit,*popt) + FWHM=popt[2] + center=popt[1] + elif fct == 'poly': + PolyRank=FWHM_or_PolyOrder + coefs = poly.polyfit(xdata, ydata, PolyRank) + yfit = poly.polyval(xfit, coefs) + result='' + for i in list(range(len(coefs))): + result=result+'a'+str(i)+' = '+str(round(coefs[i],3))+'\n' + print(result) + center=coefs + + if fct != 'poly': + print('Center: ',center) + print('FWHM: ',FWHM) + print('\n') + + + if graph == True: + center=round(center,4) + fig,(ax1)=plt.subplots(1,1) + fig.set_size_inches(5,4) + ax1.plot(xdata,ydata,label='mda #'+str(scannum),marker=marker) + ax1.plot(xfit,yfit,label='fit @ '+str(center)[0:6]) + ax1.set(ylabel=y_name) + ax1.set(xlabel=x_name) + ax1.ticklabel_format(style='sci', axis='y', scilimits=(0,0)) + ax1.grid(color='lightgray', linestyle='-', linewidth=0.5) + ax1.legend(shadow=True, title=title, fancybox=True) + + return center + + +def fit_centroid(n): + fit_mda(n,25,0,'poly',graph=False) + +def centroid_avg(scannum,det=25): # det = detector number for centroid position + avg=round(fit_mda_poly(scannum,det,0,graph=None)[0],2) + return avg + + +def fit_mda_gauss(scannum,det,FWHM,xrange=None,title='',marker='x',graph=1, filepath=None,prefix=None,scanIOC=None): + fct='gauss' + fit_mda(scannum,det,FWHM,fct,xrange,title,marker,graph, filepath,prefix,scanIOC) + + +def fit_mda_lorz(scannum,det,FWHM,xrange=None,title='',marker='x',graph=1, filepath=None,prefix=None,scanIOC=None): + fct='lorz' + fit_mda(scannum,det,FWHM,fct,xrange,title,marker,graph, filepath,prefix,scanIOC) + + +def fit_mda_erf(scannum,det,FWHM,xrange=None,title='',marker='x',graph=1, filepath=None,prefix=None,scanIOC=None): + fct='erf' + fit_mda(scannum,det,FWHM,fct,xrange,title,marker,graph, filepath,prefix,scanIOC) + +def fit_mda_poly(scannum,det,PolyRank,xrange=None,title='',marker='x',graph=1, filepath=None,prefix=None,scanIOC=None): + fct='poly' + fit_mda(scannum,det,PolyRank,fct,xrange,title,marker,graph, filepath,prefix,scanIOC) + + +def fit_mda_box(scannum,det,FWHM,xrange=None,title='',marker='x',graph=1, filepath=None,prefix=None,scanIOC=None): + fct='box' + fit_mda(scannum,det,FWHM,fct,xrange,title,marker,graph, filepath,prefix,scanIOC) + + + + + + + + +############################################################################################### +######################################### hkl ################################### +############################################################################################### + + + +def plot_hkl(mydata,n,x,y,title='',nlabel=''): + """mydata = instance of mdaFile object + n = scan number or [scan number1, ..., scan number N] + x = h, k or l index (D##) + d = detector index (D##) + """ + if type(n) == int: + maxpts=mydata.dim1[n].curr_pt + x_index=mydata.dim1[n].kappaDet()[x][0] + y_index=mydata.dim1[n].kappaDet()[y][0] + x_name =mydata.dim1[n].d[x_index].desc + y_name =mydata.dim1[n].kappaDet()[y][2] + plt.plot(mydata.dim1[n].d[x_index].data[:maxpts],mydata.dim1[n].d[y_index].data[:maxpts],label='scan #'+str(n)+' '+nlabel) + elif type(n) == list: + for i,j in enumerate(n): + maxpts=mydata.dim1[j].curr_pt + x_index=mydata.dim1[j].kappaDet()[x][0] + y_index=mydata.dim1[j].kappaDet()[y][0] + x_name =mydata.dim1[j].d[x_index].desc + y_name =mydata.dim1[j].kappaDet()[y][2] + try: + curve_label='scan #'+str(j)+' '+nlabel[i] + except: + curve_label='scan #'+str(j) + plt.plot(mydata.dim1[j].d[x_index].data[:maxpts],mydata.dim1[j].d[y_index].data[:maxpts],label=curve_label) + else: + print('n must be a single scan (int) or a list of scan') + return + plt.xlabel(x_name) + plt.ylabel(y_name) + plt.locator_params(tight=None,nbins=5,axis='x') + plt.legend(ncol=1, shadow=True, title=title, fancybox=True,loc='center left', bbox_to_anchor=(1, 0.5)) + plt.grid(color='lightgray', linestyle='-', linewidth=0.5) + plt.show() + + +def fit_hkl(mydata,n,pos,det,FWHM,fct='gauss',xrange=None,title='',marker='x',graph=1): + """ + mydata = instance of the class mdaFile + n = scan number + pos = D## for positioner + det = D## for detector + FWHM = width estimate + fct = 'gauss' or 'lorz' + xrange = [x1,x2] subrange for fit + """ + + + x_index=mydata.dim1[n].kappaDet()[pos][0] + y_index=mydata.dim1[n].kappaDet()[det][0] + x_name =mydata.dim1[n].d[x_index].desc + y_name =mydata.dim1[n].kappaDet()[det][2] + + x=mydata.dim1[n].d[x_index].data + y=mydata.dim1[n].d[y_index].data + + def closest(lst, K): + return lst[min(range(len(lst)), key = lambda i: abs(lst[i]-K))] + + if xrange is not None: + x1=closest(x,xrange[0]) + x2=closest(x,xrange[1]) + xrange=[np.where(x==x1),np.where(x==x2)] + xmin=min(xrange) + xmax=max(xrange) + xmin=min(xrange[0][0]) + xmax=max(xrange[1][0]) + xcrop=x[xmin:xmax] + ycrop=y[xmin:xmax] + xdata = np.array(xcrop) + ydata = np.array(ycrop) + else: + xdata = np.array(x) + ydata = np.array(y) + + Imax=np.max(ydata) + x0=xdata[np.where(ydata==Imax)][0] + + nPt_gaus=200 + xfit = np.linspace(min(x),max(x), nPt_gaus) + + + def lorentzian( x, amp, x0, gam ): + return amp * gam**2 / ( gam**2 + ( x - x0 )**2) + + def gaussian(x, amp, cen, wid): + return amp*np.exp(-np.power(x - cen, 2.) / (2 * np.power(wid, 2.))) + + if fct == 'gauss': + best_vals, covar = curve_fit(gaussian, xdata, ydata, p0=[Imax, x0, FWHM]) #5 p0=[amp,cen,wid] + yfit=gaussian(xfit,*best_vals) + elif fct == 'lorz': + best_vals, covar = curve_fit(lorentzian, xdata, ydata, p0=[Imax, x0, FWHM]) #5 p0=[amp,cen,wid] + yfit=lorentzian(xfit,*best_vals) + else: + print('Not a valid function: fct = "gauss" or fct = "lorz"') + return + + FWHM=2.355*best_vals[2] + center=best_vals[1] + print('Amplitude: ',best_vals[0]) + print('Center: ',center) + print('FWHM: ',FWHM) + + if graph is not None: + fig,(ax1)=plt.subplots(1,1) + fig.set_size_inches(5,4) + ax1.plot(xdata,ydata,label='data',marker=marker) + ax1.plot(xfit,yfit,label='fit @ '+str(center)[0:6]) + ax1.set(ylabel=y_name) + ax1.set(xlabel=x_name) + ax1.locator_params(tight=None,nbins=5,axis='x') + ax1.ticklabel_format(style='sci', axis='y', scilimits=(0,0)) + ax1.grid(color='lightgray', linestyle='-', linewidth=0.5) + ax1.legend(shadow=True, title=title, fancybox=True) + + return center + + +def fit_d4(n=LastMDA()): + d4=fit_mda(n,34,0.1,'gauss',title='mda_'+str(n).zfill(4)) + return round(d4,3) + +def fit_d3(n=LastMDA()): + d3=fit_mda(n,33,3,'gauss',title='mda_'+str(n).zfill(4)) + return round(d3,3) + +def fit_z(n=LastMDA(),d=33): + z=fit_mda(n,d,500,'erf',title='mda_'+str(n).zfill(4)) + return round(z,0) + +def plotd(): + dets=[34,33,35] + n=LastMDA() + d=dets[caget('29idKappa:det:set')] + plot_mda(n,d,title='mda_'+str(n).zfill(4)) + + + +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 read_hkl_old(n,user=None,run=None): +# h=[] +# k=[] +# l=[] +# if user is None: user=MDA_CurrentUser() +# if run is None: run=MDA_CurrentRun() +# with open('/home/beams/29IDUSER/Documents/User_Folders/'+user+'/hkl/scan_'+str(n)+'.txt') as csv_file: +# csv_f=csv.reader(csv_file,delimiter=',') +# for row in csv_f: +# if not row[0]=='h': +# h.append(float(row[0])) +# k.append(float(row[1])) +# l.append(float(row[2])) +# return np.array(h), np.array(k), np.array(l) + +# def plot_hkl_old(mydata,n1,n2=None,which='h',det=39,cropMin=None,cropMax=None,title=''): +# D=mydata.kappaDet(n1) +# d=D[det][1] +# if which == 'h': +# m = 0 +# if which == 'k': +# m = 1 +# if which == 'l': +# m = 2 + +# plt.figure(num=None, figsize=(6, 6), dpi=80, facecolor='w', edgecolor='k') +# if n2 == None: +# n=n1 +# #dif=len(read_hkl(n)[m])-mydata.dim1[n].curr_pt +# if cropMax is not None: +# x=read_hkl(n)[m][cropMin:-cropMax] +# else: +# x=read_hkl(n)[m][cropMin:] + +# plt.plot(x,mydata.dim1[n].d[d].data,label='scan #'+str(n),marker='+') +# else: +# for n in range(n1,n2+1): +# #dif=len(read_hkl(n)[m])-mydata.dim1[n].curr_pt +# if cropMax is not None: +# x=read_hkl(n)[m][cropMin:-cropMax] +# else: +# x=read_hkl(n)[m][cropMin:] + +# plt.plot(x,mydata.dim1[n].d[d].data,label='scan #'+str(n),marker='+') +# plt.xlabel(which) +# plt.ylabel(D[det][-1]) +# plt.legend(ncol=1, shadow=True, title=title, fancybox=True,loc='center left', bbox_to_anchor=(1, 0.5)) +# #plt.title(title) +# plt.grid(color='lightgray', linestyle='-', linewidth=0.5) +# plt.show() + + + +# def fit_hkl_gauss_old(scannum,det,FWHM,which='l',cropMin=None,cropMax=None,xrange=None,title='',marker='x',graph=1): +# motor,y,motor_name,y_name=mda_1D(scannum,det,1,0) +# if which == 'h': +# m = 0 +# if which == 'k': +# m = 1 +# if which == 'l': +# m = 2 +# if cropMax is not None: +# x=read_hkl(scannum)[m][cropMin:-cropMax] +# else: +# x=read_hkl(scannum)[m][cropMin:] +# def closest(lst, K): +# return lst[min(range(len(lst)), key = lambda i: abs(lst[i]-K))] + +# if xrange is not None: +# x1=closest(x,xrange[0]) +# x2=closest(x,xrange[1]) +# xrange=[np.where(x==x1),np.where(x==x2)] +# xmin=min(xrange) +# xmax=max(xrange) +# xmin=min(xrange[0][0]) +# xmax=max(xrange[1][0]) +# xcrop=x[xmin:xmax] +# ycrop=y[xmin:xmax] +# xdata = np.array(xcrop) +# ydata = np.array(ycrop) +# else: +# xdata = np.array(x) +# ydata = np.array(y) + +# Imax=np.max(ydata) +# x0=xdata[np.where(ydata==Imax)][0] + +# nPt_gaus=200 +# xfit = np.linspace(min(x),max(x), nPt_gaus) + +# def gaussian(x, amp, cen, wid): +# return amp*np.exp(-np.power(x - cen, 2.) / (2 * np.power(wid, 2.))) + +# best_vals, covar = curve_fit(gaussian, xdata, ydata, p0=[Imax, x0, FWHM]) #5 p0=[amp,cen,wid] +# yfit=gaussian(xfit,*best_vals) +# FWHM=2.355*best_vals[2] +# center=best_vals[1] +# print('Amplitude: ',best_vals[0]) +# print('Center: ',center) +# print('FWHM: ',FWHM) + +# if graph is not None: +# fig,(ax1)=plt.subplots(1,1) +# fig.set_size_inches(5,4) +# ax1.plot(xdata,ydata,label='data',marker=marker) +# ax1.plot(xfit,yfit,label='fit @ '+str(center)[0:6]) +# ax1.set(ylabel=y_name) +# ax1.set(xlabel=which) +# ax1.ticklabel_format(style='sci', axis='y', scilimits=(0,0)) +# ax1.grid(color='lightgray', linestyle='-', linewidth=0.5) +# ax1.legend(shadow=True, title=title, fancybox=True) + +# 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('scanIOC',BL_ioc()) + + kwargs.setdefault('filepath',MDA_CurrentDirectory(kwargs['scanIOC'])) + kwargs.setdefault('prefix',kwargs['scanIOC']+"_") + + 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',MDA_CurrentDirectory()) + kwargs.setdefault('ref_prefix',BL_ioc()+"_") + + 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',MDA_CurrentDirectory()) + kwargs.setdefault('prefix',BL_ioc()+"_") + kwargs.setdefault('scanIOC',BL_ioc()) + 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',MDA_CurrentDirectory()) + kwargs.setdefault('ref_prefix',BL_ioc()+"_") + 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',MDA_CurrentDirectory()) + kwargs.setdefault('prefix',BL_ioc()+"_") + kwargs.setdefault('scanIOC',BL_ioc()) + 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',MDA_CurrentDirectory()) + kwargs.setdefault('ref_prefix',BL_ioc()+"_") + 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',MDA_CurrentDirectory()) + kwargs.setdefault('prefix',BL_ioc()+"_") + kwargs.setdefault('scanIOC',BL_ioc()) + 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',MDA_CurrentDirectory()) + kwargs.setdefault('ref_prefix',BL_ioc()+"_") + 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',MDA_CurrentDirectory()) + kwargs.setdefault('prefix',MDA_CurrentPrefix()) + + 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(ca2flux(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=MDA_CurrentDirectory() + if prefix == None: + prefix=MDA_CurrentPrefix()[:-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=MDA_CurrentDirectory() + if prefix == None: + prefix=MDA_CurrentPrefix()[:-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=MDA_CurrentDirectory() + if prefix == None: + prefix=MDA_CurrentPrefix()[:-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=MDA_CurrentDirectory() + if prefix == None: + prefix=MDA_CurrentPrefix()[:-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',MDA_CurrentDirectory()) + kwargs.setdefault('prefix',MDA_CurrentPrefix()) + 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)) + + SetSlit_BL() + 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 + + + + + + +############################################################################################### +######################################### Object Oriented ##################################### +############################################################################################### + +class _mdaData(scanDim): + + def __init__(self): + scanDim.__init__(self) + self.poslist = None + self.detlist = None + + + def _getDetIndex(self,d): + """ + d = det Num + """ + D=self.detlist + if D==[]: + print('Data contains no detectors. Try higher dimensions: mydata.dim2[n]') + index=[None] + else: + index=[x for x, y in enumerate(D) if y[1] == 'D'+str(d).zfill(2)] + if index == []: + print('Detector '+str(d)+' not found.') + index=[None] + return index[0] + + + + def plt(self,d): + d=self._getDetIndex(d) + if d== None: + return + x=self.p[0] + y=self.d[d] + if self.dim == 2: + print('This is a 2D scan; use method mydata.img(n,d)') + for i in range(len(y.data)): + plt.plot(x.data[i], y.data[i],label=y.fieldName,marker='+') # crop aborted scans (curr_pt<npts) + else: plt.plot(x.data[:self.curr_pt], y.data[:self.curr_pt],label=y.fieldName,marker='+') # crop aborted scans (curr_pt<npts) + plt.xlabel(x.name) + plt.ylabel(y.name) + plt.legend() + plt.grid(color='lightgray', linestyle='-', linewidth=0.5) + + + + def kappaDet(self,q=None): + if q is not None: + print('\nUse detIndex for plot: mydata.dim1[n].d[detIndex].data\nIf D=mydata.dim1[n].kappaDet => detIndex=D[detNum][1]\n') + print('key = (detIndex, detNum, description, pv)') + det={} + D=self.detlist + for (i,j) in zip([32,33,34,35,31,36,37,38,39,41,42,43,44,45,46,47,48,54,55,56,57],['TEY','D3','D4','MCP','mesh','TEY / mesh','D3 / mesh','D4 / mesh','MCP / mesh','ROI1','ROI2','ROI3','ROI4','ROI5','<H>','<K>','<L>','tth','th','chi','phi']): + d=self._getDetIndex(i) + if d != None: + det[i]=(d,D[d][1],j,D[d][2]) + else: + det[i]=None + return det + + + + + +class _mdaHeader: + def __init__(self): + self.all = None + self.sample = None + self.mono = None + self.ID = None + self.energy = None + self.det = None + self.motor = None + self.mirror = None + self.centroid = None + self.slit=None + self.comment=None + + + + +class mdaFile: + + + '''mydata=mdaFile(first=0,last=None,name=datasetName,filepath=None,prefix=None) + + /net/s29data/export/data_29idb/2020_3/mda/Kappa_0107.mda is a 1-D file; 1 dimensions read in. + + mydata.header[n] = dictionary of 163 scan-environment PVs + + usage: mydata.header[n]['sampleEntry'] -> ('description', 'unit string', 'value', 'EPICS_type', 'count') + + mydata.dim1[n] = 1D data from '29idKappa:scan1' acquired on Oct 20, 2020 19:06:23: + 33/33 pts; 1 positioners, 65 detectors + + usage: mydata.dim1[n].p[2].data -> 1D array of positioner 1 data + + Each scan dimension (i.e., dim1, dim2, ...) has the following fields: + time - date & time at which scan was started: Oct 20, 2020 19:06:23 + name - name of scan record that acquired this dimension: 29idKappa:scan1 + curr_pt - number of data points actually acquired: 33 + npts - number of data points requested: 33 + nd - number of detectors for this scan dimension: 65 + d[] - list of detector-data structures + np - number of positioners for this scan dimension: 1 + p[] - list of positioner-data structures + nt - number of detector triggers for this scan dimension: 1 + t[] - list of trigger-info structures + + Each detector-data structure (e.g., dim[1].d[0]) has the following fields: + desc - description of this detector + data - data list + unit - engineering units associated with this detector + fieldName - scan-record field (e.g., 'D01') + + Each positioner-data structure (e.g., dim[1].p[0]) has the following fields: + desc - description of this positioner + data - data list + step_mode - scan mode (e.g., Linear, Table, On-The-Fly) + unit - engineering units associated with this positioner + fieldName - scan-record field (e.g., 'P1') + name - name of EPICS PV (e.g., 'xxx:m1.VAL') + readback_desc - description of this positioner + readback_unit - engineering units associated with this positioner + readback_name - name of EPICS PV (e.g., 'xxx:m1.VAL') + ''' + + def __init__(self,first=1,last=None,name='mydata',filepath=None,prefix=None,q=False): + if filepath == None: + filepath = MDA_CurrentDirectory() + self.path = filepath + self._name = name + self._first = first + self._last = last + if prefix != None and prefix[-1]=='_': + self._prefix= prefix[:-1] + else: + self._prefix= prefix + + self._allFiles = None + self._allPrefix = None + self.loadedFiles = None + self.scanList = None + self.dim1 = None + self.dim2 = None + self.dim3 = None + self.header = None + + self._extractFiles() + self._extractData(q) + + + #def __str__(self): + + + + def _extractFiles(self): + allFiles = [f for f in listdir(self.path) if isfile(join(self.path, f))] + loadedFiles= [x for (i,x) in enumerate(allFiles) if allFiles[i].split('.')[-1]=='mda'] + allPrefix = [loadedFiles[i][:loadedFiles[i].find('_')] for (i,x) in enumerate(loadedFiles)] + scanList = [int(loadedFiles[i][loadedFiles[i].find('_')+1:loadedFiles[i].find('_')+5]) for (i,x) in enumerate(loadedFiles)] + if self._prefix != None: + allPrefix=[s for s in allPrefix if s == self._prefix] + scanList = [int(loadedFiles[i][loadedFiles[i].find('_')+1:loadedFiles[i].find('_')+5]) for (i,x) in enumerate(loadedFiles) if loadedFiles[i][:loadedFiles[i].find('_')] == self._prefix] + loadedFiles = [s for s in loadedFiles if s[:s.find('_')] == self._prefix] + else: + self._prefix=allPrefix[-1] + if allPrefix[0]!=allPrefix[-1]: + print('\nWARNING: Found more than one file prefix: {}, {}.\n\nData with the same scan number will be overwriten in the order they are loaded. \nPlease specify the one you want to load with arg prefix="which".\n\n'.format(allPrefix[0],allPrefix[-1])) + if self._last == None: + self._last = self._first + shortlist = [i for (i,x) in enumerate(scanList) if self._first<=x<=self._last] + self._allFiles = allFiles + self.loadedFiles = [loadedFiles[i] for i in shortlist] + self.scanList = [scanList[i] for i in shortlist] + self._allPrefix=[allPrefix[i] for i in shortlist] + + + def _extractData(self,q): + + allheader = {} + alldata1 = {} + alldata2 = {} + alldata3 = {} + + for (i,mda) in enumerate(self.loadedFiles): + + ##### File info: + + filename=mda + filepath=self.path + #print(filepath) + num=self.scanList[i] + #print(num) + fullpath=join(filepath,filename) + #print(fullpath) + data=readMDA(fullpath,useNumpy=True) # data = scanDim object of mda module + + ###### Extract header: + + D0 = _mdaHeader() # initiate D0 = mdaHeader object + D1 = _mdaData() + D2 = _mdaData() + D3 = _mdaData() + + D=[] + + for d in range(0,4): + if d in range(0,len(data)): D.append(data[d]) + else: D.append(None) + + # D[0]=data[0] + # D[1]=data[1] + # D[2]=None if 1D data, data[2] if 2D data + # D[3]=None if 2D data, data[3] if 3D data + + + D0.all=D[0] + + + if filename[:5] == 'Kappa': + try: + D0.sample={**{key:value[:3] for key, value in D[0].items() if '29idKappa:m' in key},**{key:value[:3] for key, value in D[0].items() if '29idKappa:Euler' in key},**{key:value[:3] for key, value in D[0].items() if 'LS331' in key}} + D0.mirror = {key:value[:3] for key, value in D[0].items() if '29id_m3r' in key} + D0.centroid={key:value[:3] for key, value in D[0].items() if 'ps6' in key.lower()} + D0.det = {key:value[:3] for key, value in D[0].items() if '29idd:A' in key} + detkeys=['29idMZ0:scaler1.TP','29idKappa:m9.RBV','29idKappa:userCalcOut10.OVAL','29iddMPA:C0O','29idKappa:userStringSeq6.STR1','29idd:Unidig1Bo0'] + for k in detkeys: + if k in D[0]: D0.det[k]=D[0][k][:3] + D0.ID={key:value[:3] for key, value in D[0].items() if 'ID29' in key} + D0.UB={key:value[:3] for key, value in D[0].items() if 'UB' in key} + D0.mono={key:value[:3] for key, value in D[0].items() if 'mono' in key} + D0.energy={key:value[:3] for key, value in D[0].items() if 'energy' in key.lower()} + D0.motor = {key:value[:3] for key, value in D[0].items() if '29idb:m' in key} + D0.slit={key:value[:3] for key, value in D[0].items() if 'slit3d' in key.lower()} + except: + pass + if filename[:5] == 'ARPES': + try: + #D0.sample={**{key:value[:3] for key, value in D[0].items() if '29idKappa:m' in key},**{key:value[:3] for key, value in D[0].items() if '29idKappa:Euler' in key},**{key:value[:3] for key, value in D[0].items() if 'LS331' in key}} + #D0.mirror = {key:value[:3] for key, value in D[0].items() if '29id_m3r' in key} + #D0.centroid={key:value[:3] for key, value in D[0].items() if 'ps6' in key.lower()} + #D0.det = {key:value[:3] for key, value in D[0].items() if '29idd:A' in key} + #detkeys=['29idMZ0:scaler1.TP','29idKappa:m9.RBV','29idKappa:userCalcOut10.OVAL','29iddMPA:C0O','29idKappa:userStringSeq6.STR1','29idd:Unidig1Bo0'] + #for k in detkeys: + # if k in D[0]: D0.det[k]=D[0][k][:3] + D0.ID={key:value[:3] for key, value in D[0].items() if 'ID29' in key} + #D0.UB={key:value[:3] for key, value in D[0].items() if 'UB' in key} + D0.mono={key:value[:3] for key, value in D[0].items() if 'mono' in key} + D0.energy={key:value[:3] for key, value in D[0].items() if 'energy' in key.lower()} + D0.motor = {key:value[:3] for key, value in D[0].items() if '29idb:m' in key} + D0.slit={key:value[:3] for key, value in D[0].items() if 'slit3c' in key.lower()} + except: + pass + + try: + cmt1=D[0]['29id'+self._prefix+':saveData_comment1'][2] + cmt2=D[0]['29id'+self._prefix+':saveData_comment2'][2] + if cmt2 != '': D0.comment = cmt1+' - '+cmt2 + else: D0.comment = cmt1grid + except: + D0.comment = '' + + + ###### Extract data: + + DIMS=[D1,D2,D3] + + for counter, value in enumerate(DIMS): + c=counter+1 + if D[c] is not None: + value.rank=D[c].rank + value.dim=D[c].dim + value.npts=D[c].npts + value.curr_pt=D[c].curr_pt + value.plower_scans=D[c].plower_scans + value.name=D[c].name # + value.time=D[c].time + value.np=D[c].np + value.p=D[c].p + value.nd=D[c].nd + value.d=D[c].d + value.nt=D[c].nt + value.t=D[c].t + value.detlist=[(i,D[c].d[i].fieldName,D[c].d[i].name,D[c].d[i].desc) for i in range(0,D[c].nd)] + value.poslist=[(i,D[c].p[i].fieldName,D[c].p[i].name,D[c].p[i].desc) for i in range(0,D[c].np)] + else: + value=None + + allheader[num] = D0 + alldata1[num] = D1 + alldata2[num] = D2 + alldata3[num] = D3 + + d=D.index(None)-1 + if q is False: + print('Loading {} as {}.dim{}[{}]:\n\t\t...{}D data, {}/{} pts; {} positioners, {} detectors'.format( + filename,self._name,d,self.scanList[i],D[d].dim,D[d].curr_pt, D[d].npts, D[d].np, D[d].nd)) + + self.header=allheader + self.dim1=alldata1 + self.dim2=alldata2 + self.dim3=alldata3 + + + + + + def updateFiles(self,first=0,last=inf,name=None,filepath=None,prefix=None): + new=mdaFile(first,last,name,filepath,prefix) + self.loadedFiles=list(dict.fromkeys(self.loadedFiles+new.loadedFiles)) + self._allFiles=list(dict.fromkeys(self._allFiles+new._allFiles)) # merging the 2 list and removing duplicates + self.scanList=list(dict.fromkeys(self.scanList+new.scanList)) + self._allPrefix=list(dict.fromkeys(self._allPrefix+new._allPrefix)) + self.dim1.update(new.dim1) + self.dim2.update(new.dim2) + self.dim3.update(new.dim3) + self.header.update(new.header) + return self + + + + def plt(self,*argv): + if self.dim2[argv[0]].dim == 0: #1D scan + for index,arg in enumerate(argv): + if index %2 !=0: + pass + else: + n=arg + d=argv[index+1] + d=self.dim1[n]._getDetIndex(d) + x=self.dim1[n].p[0] + y=self.dim1[n].d[d] + plt.plot(x.data[:self.dim1[n].curr_pt], y.data[:self.dim1[n].curr_pt],label='mda #'+str(n)+' - '+y.fieldName,marker='+') + plt.xlabel(x.name) + plt.ylabel(y.name+' - ('+y.fieldName+')') + plt.legend() + plt.grid(color='lightgray', linestyle='-', linewidth=0.5) + plt.show() + elif self.dim2[argv[0]].dim == 2: # 2D scan + for index,arg in enumerate(argv): + if index %2 !=0: + pass + else: + n=arg + d=argv[index+1] + d=self.dim2[n]._getDetIndex(d) + if d == None: + return + x=self.dim2[n].p[0] + y=self.dim1[n].p[0] + z=self.dim2[n].d[d] + zlim=self.dim2[n].curr_pt + fig, ax0 = plt.subplots() + img = ax0.imshow(z.data[:zlim],cmap='gnuplot', interpolation = 'nearest', extent = [min(x.data[0]), max(x.data[0]), min(y.data),max(y.data)], aspect = 'auto') + fig.colorbar(img) + plt.title(z.name+' - ('+z.fieldName+')') + ax0.set_xlabel(x.name) + ax0.set_ylabel(y.name) + plt.show() + + + + + + + diff --git a/macros_and_scripts/alignment_commissioning.py b/macros_and_scripts/commissioning.py similarity index 55% rename from macros_and_scripts/alignment_commissioning.py rename to macros_and_scripts/commissioning.py index 3b7f51adb315512036e1260f7f798fbba0a2d0e0..6bf488cf3a1fd5499e510e1e1f9197530f8b7a22 100644 --- a/macros_and_scripts/alignment_commissioning.py +++ b/macros_and_scripts/commissioning.py @@ -4,33 +4,53 @@ 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 -from files_and_folders import check_run, folder_mda -from scanRecord import scanRecord_run,scanRecord_filepath -from beamline import energy -from M3R import M3R_branch -from ARPES import folders_ARPES -from Kappa import folders_Kappa -from IEX_VPU import ID_switch_mode -from diagnostics import diagnostics_all_out, diagnostics_all_in,diodeC,diodeD -from diagnostics import diodeC_read,diodeD_read -from current_amplifiers import ca2flux -from slits import set_exit_slit +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 ..instruments.IEX_VPU import ID_switch_mode +from ..instruments.diagnostics import diagnostics_all_out, diagnostics_all_in,diodeC,diodeD +from ..instruments.current_amplifiers import current2flux +from ..instruments.slits import set_exit_slit +from ..instruments.logfile import * + +from ..instruments.ARPES import * +from ..instruments.electron_analyzer import * +from ..instruments.Kappa import * +from .ScanFunctions_plot import fit_mda, mda_1D + ############################################################################################################## ################################ setting the mda folder ############################## ############################################################################################################## - -def folders_staff(BL): +def staff_init(endstation_name=None,set_folders=True,reset=True): """ - sets the scan record for Endstation to the Staff folder + 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 """ - run=scanRecord_run(BL.ioc) - folder_mda(run,'b','Staff',BL.name,BL.ioc) + 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): """ @@ -75,24 +95,30 @@ def check_staff_directory(BL, **kwargs): ############################################################################################################## def check_flux(hv=500,ID_mode='RCP',stay=False): + """ + puts the diode in + measures flux at energy ID_mode specified + stay: diode position after the scan + + Previously: CheckFlux + """ ID_switch_mode(ID_mode) energy(hv) - branch=M3R_branch() - diagnostics_all_out(diode_to_stay_in=branch) + diagnostics_all_out(diode_to_stay_in=m3r_branch()) SR=round(caget("S:SRcurrentAI.VAL"),2) - if branch == "c": + if m3r_branch() == "c": current_slit=caget('29idb:Slit3CFit.A') diodeC('In') set_exit_slit(50) sleep(10) diode=diodeC_read() - elif branch == "d": + elif m3r_branch() == "d": current_slit=caget('29idb:Slit4Vsize.VAL') sleep(10) diodeD("In") set_exit_slit(50) diode=caget('29idb:ca14:read') - flux=ca2flux(diode) + flux=current2flux(diode) print("\n----- Current on diode : %.3e" % diode, "A") print("----- Corresponding flux: %.3e" % flux, "ph/s \n") print("----- Storage ring current: %.2f" % SR, "mA") @@ -112,125 +138,100 @@ def check_m0m1(hv=500,stay=True,wire=True,**kwargs): Previously: CheckM0M1 """ - Switch_Branch('c') - Switch_Grating('HEG') + switch_branch('c') + switch_gratings('HEG') print("\nFlux at hv=500 as off Feb 2019: ~3.3e-06 A = ~1.5e+11 ph/s") - Open_BranchShutter() - CheckFlux(hv=hv,stay=stay) + branch_shutter_open() + check_flux(hv=hv,stay=stay) if wire is not None: - WireScan('H',scanIOC,**kwargs) - WireScan('V',scanIOC,**kwargs) + scan_wire('H',**kwargs) + scan_wire('V',**kwargs) -def WireScan(which,scanIOC=None,all_diag=True,**kwargs): +def scan_wire(direction,all_diag=True,**kwargs): """ Scans the wires located just downstream of M0/M1, which = 'H' for the horizontal, typically CA2 which = 'V' for the vertical, typically CA3 all_diag =True -> AllDiagIn(), otherwise you have to put any diagnostics in by hand Logging is automatic: use **kwargs or the optional logging arguments see scanlog() for details + **kwargs: + execute """ - - if scanIOC is None: - scanIOC=BL_ioc() + kwargs.setdefault('execute',True) if all_diag: - AllDiagIn() - if which=='H': - print("\n================== H wire scan (29idb:ca3):") - Scan_FillIn("29idb:m1.VAL","29idb:m1.RBV",scanIOC,1,-13,-27,-0.25) - - elif which=='V': - print("\n================== V wire scan (29idb:ca2):") - Scan_FillIn("29idb:m2.VAL","29idb:m2.RBV",scanIOC,1,-17,-30,-0.25) - Scan_Go(scanIOC,scanDIM=1,**kwargs) - if all_diag: - AllDiagOut() - - def MIR_GRT_Offset(GRT,Slit_list): - """ "Find MIR-GRT offset by scanning 0 order through exit slit""" - Switch_Grating(GRT) - SetExitSlit(50) - scanIOC="Test" - DiodeC('In') - SetSlit2B(2,0.5,0,0) - VAL="29idmonoGRT:P_SP" - for ang in RangeUp(1.5,5,0.5): - print("\r") - Mono_angle(ang,ang) - print("\r") - for x in Slit_list: - SetExitSlit(x) - print("\r") - caput("29idTest:scan1.PASM",3) # go to peak position - caput("29idTest:scan1.REFD",44) - start,stop,step = ang-0.0005*x, ang+0.0005*x ,0.00002*x - Scan_FillIn(VAL,"",scanIOC,1,start,stop,step) - Scan_Go(scanIOC,scanDIM=1) - sleep(1) - print("\r") - ang=caget("29idmonoGRT:P_SP") - print("Peak: ",ang) - print("\r") - print("-------------------------") - caput("29idTest:scan1.PASM",2) - caput("29idTest:scan1.REFD",1) + diagnostics_all_in() + + + if direction == 'H': + name = "H-wire" + elif direction == 'V': + name = "V-wire" + 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) + + if kwargs['execute']: + BL.mda.go(**kwargs) + + if all_diag: + diagnostics_all_out() ############################################################################################################## ########################### Beam Profile ###################### ############################################################################################################## - - - -def Scan_NarrowSlit(which='2V',slit_parameters=[0.25,-2,2,0.5],scanDIM=1,scanIOC=None): +def scan_narrow_slit(slit='2V',slit_parameters=[0.25,-2,2,0.5],**kwargs): """ - which='1V','1H','2V','2H' + slit = '1V','1H','2V','2H' slit_parameters = [SlitSize,start,stop,step] Typical slit sizes/start/stop/step are (for full range): 1H/1V : [0.50, -4.5, 4.5, 0.2] 2H : [0.25, -3.0, 3.0, 0.2] 2V-MEG: [0.25, -4.0, 4.0, 0.2] - 2V-HEG: [0.50, -8.0, 8.0, 0.2] + 2V-HEG: [0.50, -8.0, 8.0, 0.2] + + **kwargs: + scan_dim = 1 + execute = True + + Previously: Scan_NarrowSlit """ - if scanIOC == None: - scanIOC=BL_ioc() + kwargs.setdefault('scan_dim',1) + kwargs.setdefault('execute',True) + size,start,stop,step = slit_parameters - - SlitDict={"V":(inf,size),"H":(size,inf),'1':'2','2':'1'} ## very complicated stuff to make a narrow slit along the direction perpendicular to the scan, and open the other slit all the way - Hsize=SlitDict[which[1]][0] - Vsize=SlitDict[which[1]][1] - scanslit=int(which[0]) - otherslit=int(SlitDict[which[0]]) - - SetSlit(scanslit,Hsize,Vsize) - SetSlit(otherslit) - if which in ['2V','2H']: - SetSlit1A(3,3,0,0) # SetSlit_BL FR added on 9/24/2020 - VAL="29idb:Slit"+which+"center.VAL" - RBV="29idb:Slit"+which+"t2.D" - Scan_FillIn(VAL,RBV,scanIOC,scanDIM,start,stop,step) - - -def Scan_NarrowSlit_Go(which='2V',slit_parameters=[0.25,-2,2,0.5],scanDIM=1,scanIOC='ARPES'): - """ - which='1V','1H','2V','2H' - slit_parameters = [SlitSize,start,stop,step] - Typical slit sizes/start/stop/step are (for full range): - 1H/1V : [0.50, -4.5, 4.5, 0.2] - 2H : [0.25, -3.0, 3.0, 0.2] - 2V-MEG: [0.25, -4.0, 4.0, 0.2] - 2V-HEG: [0.50, -8.0, 8.0, 0.2] - """ - Scan_NarrowSlit(which,slit_parameters,scanDIM,scanIOC) - Scan_Go(scanIOC,scanDIM=scanDIM) + + direction = slit[1] + if direction == "V": + size = (inf, size) + center = (0, 0) + elif direction == "H": + size = (size, inf) + center = (0, 0) + + if slit[0] == '1': + slit_name = "slit1A" + slit1A_set(size,center) + slit2B_set((inf,inf),(0,0)) + + elif slit[0] == '2': + slit_name = "slit2B" + slit1A_set((3,3),(0,0)) + slit2B_set(size,center) + + slits_scan_center(slit_name,direction,start,stop,step,**kwargs) + if kwargs['execute']: + BL.mda.go(kwargs['scan_dim']) -def Scan_MonoVsSlit(which='2V',slit_parameters=[0.25,-2,2,0.5],energy_parameters=[470,530,2],**kwargs): +def scan_mono_vs_slit(slit='2V',slit_parameters=[0.25,-2,2,0.5],energy_parameters=[470,530,2],**kwargs): """ This can be used to find the center of the resonant beam i.e. the slit value for the most blue shifted curve: - which='1V','1H','2V','2H' + slit='1V','1H','2V','2H' slit_parameters = [SlitSize,start,stop,step] energy_parameters = [eVstart,eVstop,eVstep]= [470,530,2] @@ -239,209 +240,69 @@ def Scan_MonoVsSlit(which='2V',slit_parameters=[0.25,-2,2,0.5],energy_parameters 2H : [0.25, -3.0, 3.0, 0.2] 2V-MEG: [0.25, -4.0, 4.0, 0.2] 2V-HEG: [0.50, -8.0, 8.0, 0.2] - + + Previously: Scan_MonoVsSlit """ - scanIOC=BL_ioc() - eVstart,eVstop,eVstep=energy_parameters + hv_start,hv_stop,hv_step = energy_parameters # Filling Scans: - Scan_Mono(1,eVstart,eVstop,eVstep) - caput("29id"+scanIOC+":scan1.PASM","STAY") - Scan_NarrowSlit(which,slit_parameters,2) - Scan_Go(scanIOC,2,**kwargs) + mono_scan_fillin(hv_start,hv_stop,hv_step) + scan_narrow_slit(slit='2V',slit_parameters=[0.25,-2,2,0.5],**kwargs) + # Resetting everybody to normal: - caput("29id"+scanIOC+":scan1.PASM","PRIOR POS") - SetMono((eVstart+eVstop)/2.0) - SetSlit_BL() + mono_energy_set((hv_start+hv_stop)/2.0) + slits_set_BL() + ############################################################################################################## -####################### Mono Calibration ####################### +################################ mono alignment ############################## ############################################################################################################## +def mono_MIR_GRT_find_offset(grating,slit_list,**kwargs): + """ + Find MIR-GRT offset by scanning 0 order through exit slit + **kwargs: + detNum = 15 - - - - - - - -def Mono_angle(alpha,beta): #JM modified to monitor the ready, moving sequentialy ended up in crash sometimes - """ - Sets the mirror pitch (alpha) and grating pitch (beta) angles + Previously: MIR_GRT_Offset """ - alpha=alpha*1.0 - beta=beta*1.0 - #Putting Setpoints Go - caput("29idmonoGRT:P_SP",alpha) - caput("29idmonoMIR:P_SP",beta) - ready=0 - while ready != 1: - sleep(0.1) - ready=caget('29idmono:ERDY_STS') - print("Mono set to zero order: MIR_pitch = "+str(alpha)+", GRT_pitch = "+str(beta)) - + kwargs.setdefault("detNum",15) - -def Mono_Set_b2(b2): - """ - Changes the b2 value for the current grating - """ - hvSP=caget("29idmono:ENERGY_SP") - suffix=Mono_Suffixes()[1] - caput("29idmonoGRT:B2_CALC."+suffix,b2) - sleep (1) - SetMono(hvSP) - Get_Mono() + switch_gratings(grating) + exit_slit(50) + diodeC('In') + slit2B_set(2,0.5,0,0) -def Mono_Set_cff(order,cff): - """ - Changes the cff value for the current grating - """ - which=caget("29idmonoGRT_TYPE_MON") - hvSP=caget("29idmono:ENERGY_SP") - MIR_Pitch=caget("29idmonoMIR:P.RBV") - GRT_Pitch=caget("29idmonoGRT:P.RBV") - hv=caget("29idmono:ENERGY_MON") - print('MIR & GRT Pitch:',MIR_Pitch,GRT_Pitch) - suffix=Mono_Suffixes()[1] - caput("29idmonoGRT:TUN"+str(order)+"_CALC."+suffix,cff) - sleep (1) - SetMono(hvSP) - new_MIR_Pitch=caget("29idmonoMIR:P.RBV") - new_GRT_Pitch=caget("29idmonoGRT:P.RBV") - dif_MIR_Pitch=new_MIR_Pitch-MIR_Pitch - dif_GRT_Pitch=new_GRT_Pitch-GRT_Pitch - new_hv=caget("29idmono:ENERGY_MON") - print('MIR & GRT Pitch:',new_MIR_Pitch,new_GRT_Pitch) - print('Differences :',dif_MIR_Pitch,dif_GRT_Pitch) -# Get_CFF() - - -def Mono_Set_GRT0(newGRT0): - """ - Sets ONLY the GRT_offset for the current Grating - Paralellism is NOT maintained - """ - which='GRT' - suffix=Mono_Suffixes()[1] # Mono_Suffixes() returns suffixes for current MIR [0] and GRT [1] - GRT_pv='29idmono'+which+':P_OFFSETS.'+suffix - hvSP=caget("29idmono:ENERGY_SP") - caput(GRT_pv,newGRT0) - - #Putting the energy back and printing mono parameters - sleep (1) - caput("29idmono:ENERGY_SP",hvSP) - Get_Mono() - - -def Mono_Set_MIR0(newMIR0): - """ - Sets ONLY the MIR0 for the current Grating - Paralellism is NOT maintained - """ - which='MIR' - suffix=Mono_Suffixes()[0] # Mono_Suffixes() returns suffixes for current MIR [0] and GRT [1] - GRT_pv='29idmono'+which+':P_OFFSETS.'+suffix - hvSP=caget("29idmono:ENERGY_SP") - caput(GRT_pv,newMIR0) - #Putting the energy back and printing mono parameters - sleep (1) - caput("29idmono:ENERGY_SP",hvSP) - Get_Mono() + #set zero order, scan grating pitch + for ang in RangeUp(1.5,5,0.5): + print("\r") + mono_zero_order(ang) + print("Mirror pitch: "+str(ang)+"\r") + for s in slit_list: + exit_slit(s) + print("\r") + mono_motor_scan_fillin("GRT:P",ang-0.0005*s, ang+0.0005*s ,0.00002*s) + BL.mda.go(**kwargs) + sleep(1) + print("\r") + grating_ang = fit_mda(mda.fileNum(),kwargs['detNum'],.1,'gauss') + print("Peak: ",grating_ang) + print("\r") + print("-------------------------") -def Mono_Set_MIR0_GRT0(newMIR0): - """ - Sets both the MIR0 and the GRT0 for the current Mirror and Grating - so that paralellism is maintained - """ - MIR_suffix=Mono_Suffixes()[0] # Mono_Suffixes() returns suffixes for current MIR [0] and GRT [1] - GRT_suffix=Mono_Suffixes()[1] - MIR_pv='29idmonoMIR:P_OFFSETS.'+MIR_suffix - GRT_pv='29idmonoGRT:P_OFFSETS.'+GRT_suffix - # Getting current values and current delta between GRT0 and MIR0 - hvSP=caget("29idmono:ENERGY_SP") - oldMIR0=caget(MIR_pv) - oldGRT0=caget(GRT_pv) - delta=oldGRT0-oldMIR0 - # Setting new values while maintaining delta - caput(MIR_pv,newMIR0) - caput(GRT_pv,newMIR0+delta) - #Putting the energy back and printing mono parameters - sleep (1) - caput("29idmono:ENERGY_SP",hvSP) - Get_Mono() - - -def Mono_Set_MIR0_GRT0_all(newMIR0): - """ - Sets both the MIR0 for the current mirror and the GRT0 for all grating - so that paralellism is maintained => Equivalent to moveing ExitSlit_Vcenter - """ - hvSP=caget("29idmono:ENERGY_SP") - MIR_suffix=Mono_Suffixes()[0] # Mono_Suffixes() returns suffixes for current MIR [0] and GRT [1] - MIR_pv ='29idmonoMIR:P_OFFSETS.'+MIR_suffix - GRT_pv1='29idmonoGRT:P_OFFSETS.C' - GRT_pv2='29idmonoGRT:P_OFFSETS.D' - GRT_pv3='29idmonoGRT:P_OFFSETS.E' - #Getting current values: - oldMIR0 =caget(MIR_pv) - oldGRT0_1=caget(GRT_pv1) - oldGRT0_2=caget(GRT_pv2) - oldGRT0_3=caget(GRT_pv3) - print("MIR0 : ",oldMIR0) - print("GRT0s : ",oldGRT0_1,oldGRT0_2,oldGRT0_3) - #Calculating the deltas between GRT0s and MIR0 - delta1=oldGRT0_1-oldMIR0 - delta2=oldGRT0_2-oldMIR0 - delta3=oldGRT0_3-oldMIR0 - print("GRT0(1)-MIR0", delta1) - print("GRT0(2)-MIR0", delta2) - print("GRT0(3)-MIR0", delta3) - # Setting new values while maintaining delta - caput(MIR_pv ,newMIR0) - caput(GRT_pv1,newMIR0+delta1) - caput(GRT_pv2,newMIR0+delta2) - caput(GRT_pv3,newMIR0+delta3) - #Putting the energy back and printing mono parameters - sleep (1) - caput("29idmono:ENERGY_SP",hvSP) - Get_Mono() - - - -def Mono_Set_ExitArm(distance_mm): - """ - Changes the exit arm value in mm (distance between grating and exit slit, theoritically 20000) - """ - hvSP=caget("29idmono:ENERGY_SP") - MIR_Pitch=caget("29idmonoMIR:P.RBV") - GRT_Pitch=caget("29idmonoGRT:P.RBV") - hv=caget("29idmono:ENERGY_MON") - print('MIR & GRT Pitch:',MIR_Pitch,GRT_Pitch) - caput("29idmono:PARAMETER.G",distance_mm) - sleep (1) - SetMono(hvSP) - new_MIR_Pitch=caget("29idmonoMIR:P.RBV") - new_GRT_Pitch=caget("29idmonoGRT:P.RBV") - dif_MIR_Pitch=new_MIR_Pitch-MIR_Pitch - dif_GRT_Pitch=new_GRT_Pitch-GRT_Pitch - new_hv=caget("29idmono:ENERGY_MON") - print('MIR & GRT Pitch:',new_MIR_Pitch,new_GRT_Pitch) - print('Differences :',dif_MIR_Pitch,dif_GRT_Pitch) -# Get_CFF() - - -def Mono_Set_Slitvshv(hv,c=3): +##################### mono slit scans => Energy calibration ##################### +def exit_slit_vs_hv(hv,c=3): ''' Adjust slit size to keep reasonable count vs hv - c=3 for nominal Slit2B size + c=3 for nominal slit2B size c=10 for apertured slit2B (e.g 0.25 or 0.5) + + Previously: Mono_Set_Slitvshv ''' slit(hv/100.0*c) -def Mono_Scan_Slit2BV(hv,peakBE=84,pts=11,r=0.75,i=1,**kwargs): +def scan_energy_along_grating(hv,peakBE=84,pts=11,r=0.75,i=1,**kwargs): """ Takes a Slit-2V map for a range of photon energies peakBE=84; fixed mode @@ -449,35 +310,44 @@ def Mono_Scan_Slit2BV(hv,peakBE=84,pts=11,r=0.75,i=1,**kwargs): r = % of range in slit size, default: 0.75 i = scanEA time in minute (default:1 for MEG, 2 for HEG?) Takes 2.5h with default parameters (i=1) + + Previously: Mono_Scan_Slit2BV """ - - print("\n--------------- Starting core level vs Slit-2B(V) map ---------------") - GRT=caget("29idmono:GRT_DENSITY") - c=GRT/1200 # c = 1 for MEG, 2 for HEG + grt_density = mono_grating_density_get() + c=grt_density/1200 # c = 1 for MEG, 2 for HEG + # Getting EA parameters vs hv: PE=200 + #Getting Slit-2B parameters Vsize=0.25*c n=(4.5-hv/500) Vstart=-((floor((2*n)/Vsize/2)+1)*Vsize*c)*r Vstep=-round(Vstart*2/pts,2) + #Setting energy: energy(hv) - Mono_Set_Slitvshv(hv,c=10) - #Aperturing slit 2V - caput("29idb:Slit2Vsize.VAL",Vsize) - VVAL ="29idb:Slit2Vcenter.VAL" + exit_slit_vs_hv(hv,c=10) + + #Aperturing slit 2V (note that we have the nominal size horizontally) + (size_rbv,size_val),(center_rbv,center_val) = slits_pvs('slit2B') + caput(size_val,Vsize) + + print("\n--------------- Starting core level vs Slit-2B(V) map ---------------") + #Take XPS for each Slit-2V position - for V in RangeUp(Vstart,-Vstart,Vstep): - caput(VVAL,V,wait=True,timeout=18000) - kwargs.update({'comment': "2-V center ="+str(V)[0:6]}) + for V_center in RangeUp(Vstart,-Vstart,Vstep): + caput(center_val,V_center,wait=True,timeout=18000) + kwargs.update({'comment': "2-V center ="+str(V_center)[0:6]}) EAlist=["BE",peakBE,PE,17*60*i,1] scanEA(EAlist,**kwargs) - SetSlit_BL() + + #reset the slits + slits_set_BL() -def Mono_Scan_hv_drift(start,stop,step,peakBE=84,EF=None,**kwargs): +def scan_mono_energy_drift(start,stop,step,peakBE=84,EF=None,**kwargs): ''' Measure core level (by default Au 4f) in fixed mode vs energy while maintaining resonable count rate If EF='y' (by default None) takes the Fermi edge as well. @@ -485,13 +355,15 @@ def Mono_Scan_hv_drift(start,stop,step,peakBE=84,EF=None,**kwargs): c=3 is the default slit2B size Used for grating calibration (changing grating_offset and b2 effects this - use grating_offset since b2 was measured) + + Previously: Mono_Scan_hv_drift ''' kwargs.setdefault('c','3') for hv in RangeUp(start,stop,step): energy(hv) c=int(kwargs['c']) - Mono_Set_Slitvshv(hv,c) + exit_slit_vs_hv(hv,c) kwargs.update({'comment': "Core level @ hv = "+str(hv)}) scanEA(["BE",peakBE,200,17*60*1,1],**kwargs) if EF is not None: @@ -503,69 +375,62 @@ def Mono_Scan_hv_drift(start,stop,step,peakBE=84,EF=None,**kwargs): ############################################################################################################## ########################### Pinhole Scripts ###################### ############################################################################################################## - - -def FullPinhole(): +def scan_pinhole_full(): """ - Does a pinhole with .1 mm step with AllDiagIn and then with only DiodeCIn() + Does a pinhole with .1 mm step with AllDiagIn and then with only branch diode in + + Previously: FullPinhole """ - AllDiagIn() - Scan_Pinhole_Go(-3, 3, .5, .1, -3, 3, .5, .1) - AllDiagOut() - DiodeC('In') - Scan_Pinhole_Go(-3, 3, .5, .1, -3, 3, .5, .1) + diagnostics_all_in() + scan_pinhole([-3, 3, .5, .1], [-3, 3, .1, .5]) + diagnostics_all_out(diode_stay_in=True) + scan_pinhole([-3, 3, .5, .1], [-3, 3, .1, .5]) -def Scan_Pinhole_Go(Hstart, Hstop, Hsize, Hstep,Vstart, Vstop, Vsize, Vstep,HscanDim=1,VscanDim=2,scanIOC="BL_ioc"): - """ - Sets up the pinhole scan in the specified scanIOC ( BL_ioc => BL_ioc(), else scanIOC="Kappa","ARPES","RSXS"...) - Make sure that you have the appropriate Diagnostics in can use AllDiagIn() - Scan_Pinhole_Start(-3, 3, 0.5, 0.5, -3, 3, 0.5, 0.5) - """ - Scan_Pinhole(Hstart, Hstop, Hsize, Hstep, Vstart, Vstop, Vsize, Vstep,HscanDim,VscanDim,scanIOC) - print("\r") - print("Pinhole ("+str(HscanDim)+","+str(VscanDim)+"): "+str(Hstart)+"/"+str(Hstop)+"/"+str(Hsize)+"/"+str(Hstep)+"/"+str(Vstart)+"/"+str(Vstop)+"/"+str(Vsize)+"/"+str(Vstep)) - if scanIOC == "BL_ioc": - scanIOC = BL_ioc() - Scan_Go(scanIOC,scanDIM=VscanDim) - print("\r") - print("Now setting the slits back to:") - SetSlit_BL() - print("\r") - print("WARNING: Don't forget to pull all of the diagnostics out.") - -def Scan_Pinhole(Hstart, Hstop, Hsize, Hstep,Vstart, Vstop, Vsize, Vstep,HscanDim=1,VscanDim=2,scanIOC="BL_ioc"): +def scan_pinhole(H_list,V_list,**kwargs): """ - Sets up the pinhole scan in the specified scanIOC ( BL_ioc => BL_ioc(), else scanIOC="Kappa","ARPES","RSXS"...) - Make sure that you have the appropriate Diagnostics in can use AllDiagIn() - Does not press Go + Sets up the pinhole scan for slit1A + Make sure that you have the appropriate Diagnostics in can use AllDiagIn() + + H_list = [Hstart, Hstop, Hstep, Hsize] => [-3, 3, .1, .5] + V_list = [Vstart, Vstop, Vstep, Vsize] => [-3, 3, .1, .5] + + *kwargs: + H_scan_dim => 1 + V_scan_dim => 2 + execute => True + + Previously: Scan_Pinhole_Go, Scan_Pinhole """ - if scanIOC == "BL_ioc": - scanIOC = BL_ioc() - + kwargs.setdefault('H_scan_dim',1) + kwargs.setdefault('V_scan_dim',2) + kwargs.setdefault('execute',True) + #Synching slits - caput("29idb:Slit1Hsync.PROC",1) - caput("29idb:Slit1Vsync.PROC",1) + slits_synch("slit1A") + #Getting initial slit size - Hsize0=caget("29idb:Slit1Ht2.C") - Vsize0=caget("29idb:Slit1Vt2.C") - Hcenter0=caget("29idb:Slit1Ht2.D") - Vcenter0=caget("29idb:Slit1Vt2.D") + (Hsize0,Vsize0),(Hcenter0,Vcenter0) = slit1A_get(verbose=False) + #Filling in the ScanRecord - HVAL="29idb:Slit1Hcenter.VAL" - HRBV="29idb:Slit1Ht2.D" - Hstart=1.0*Hstart - Hstop=1.0*Hstop - Hstep=1.0*Hstep - VVAL="29idb:Slit1Vcenter.VAL" - VRBV="29idb:Slit1Vt2.D" - Vstart=1.0*Vstart - Vstop=1.0*Vstop - Vstep=1.0*Vstep - Scan_FillIn(HVAL,HRBV,scanIOC,HscanDim,Hstart,Hstop,Hstep) - Scan_FillIn(VVAL,VRBV,scanIOC,VscanDim,Vstart,Vstop,Vstep) - SetSlit1A(Hsize,Vsize,0,0,q=None) - print("WARNING: The slits are now set to", str(Hsize),"x",str(Vsize)) + slits_scan_center("slit1A","H",H_list[0],H_list[1],H_list[2],scan_dim=kwargs['H_scan_dim'],execute=False) + slits_scan_center("slit1A","V",V_list[0],V_list[1],V_list[2],scan_dim=kwargs['V_scan_dim'],execute=False) + + #Set the slit size + slit1A_set((H_list[2],V_list[2]),(0,0),verbose=True) + + if kwargs['execute']: + print("\rPinhole scan: ("+str(kwargs['H_scan_dim'])+","+str(kwargs['V_scan_dim'])+") " + +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'])) + print("\rNow setting the slits back to:") + slits_set_BL() + + print("\r") + print_warning_message("Don't forget to pull all of the diagnostics out.") + ############################################################################################################## @@ -582,7 +447,7 @@ def Notes_from_20191212(): => 5 urad down = 1 mm negative motion on 2B-V with HEG""") -def Procedure_Alignment_M1(): +def procedure_alignment_M1(): print("""\n-Start with a very red shifted line cut to localize the edges of the grating: Set_IDraw(510) mono(485) @@ -599,12 +464,12 @@ def Procedure_Alignment_M1(): print('\\n') Move_M1('RZ',roll) sleep(5) - Scan_MonoVsSlit('2V',[0.25,-0.5,0.5,0.25],[490,530,2]) + 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) sleep(5) - Scan_MonoVsSlit('2H',[0.25,-0.5,0.5,0.25],[490,530,2]) + 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. WARNING: It is more accurate (and easier) to compare the leading edge of the ID peak @@ -643,7 +508,7 @@ def beamsteering_1A(h_position,v_position): ### Slit-1A Procedures ##################################################################################### -def Check_Slit1A(scanIOC=None,step=0.1): +def check_slit1A(step=0.1): """ Checks that Slit1A is centered on the fixed aperature/theoretical optic axis top='m9' -> CA5 @@ -662,32 +527,30 @@ def Check_Slit1A(scanIOC=None,step=0.1): If data makes no sense then Reset_Slit1A_Procedure() """ - if scanIOC == None: - scanIOC=BL_ioc() #scanning top-blade - - SetSlit1A(8,8,0,0) # aperture wide open + slit1A_set(8,8,0,0) # aperture wide open caput('29idb:m10.VAL',0) # Inboard blade centered-ish in the beam m=9 VAL='29idb:m'+str(m)+'.VAL' RBV='29idb:m'+str(m)+'.RBV' - Scan_FillIn(VAL,RBV,'ARPES',1,-4,4.0,step) - Scan_ARPES_Go() - FileNum1 = caget("29id"+scanIOC+":saveData_scanNumber")-1 + BL.mda.fillin(VAL,RBV,-4,4.0,step) + BL.mda.go() + FileNum1 = BL.mda.lastFileNum() #scanning inboard-blade - SetSlit1A(8,8,0,0) # aperture wide open + slit1A_set(8,8,0,0) # aperture wide open caput('29idb:m9.VAL',0) # top blade centered-ish in the beam m=10 VAL='29idb:m'+str(m)+'.VAL' RBV='29idb:m'+str(m)+'.RBV' - Scan_FillIn(VAL,RBV,'ARPES',1,-4,4.0,step) - Scan_ARPES_Go() - FileNum2 = caget("29id"+scanIOC+":saveData_scanNumber")-1 + BL.mda.fillin(VAL,RBV,-4,4.0,step) + BL.mda.go() + FileNum2 = BL.mda.lastFileNum() + return FileNum1, FileNum2 -def Procedure_Reset_Slit1A(): +def procedure_reset_slit1A(): """ Prints the procedure for Resetting Slit1A """ @@ -702,68 +565,53 @@ def Procedure_Reset_Slit1A(): print("# Then SetSlit1A(1Hsize,1Vsize,0,0); where 1Hsize and 1Vsize are the size where CA4 = 0") print(" for m in [9,10,11,12]: Reset_Motor_User(m,'b',0);SyncAllSlits()") - -def Scan_SlitCenter(slit,start,stop,step,setslit=None,scanIOC=None,scanDIM=1,**kwargs): + +def check_ID_steering(hv=2000): """ - Scans the slit center: - slit='1H','1V','2H' or '2V' - Slit 1A is set to (0.25,0.25,0,0) unless setslit= not None - Logging is automatic: use **kwargs or the optional logging arguments see scanlog() for details - default: scanDIM=1 + Scans Slit1A center (set to a (0.25,0.25) pinhole) while looking at the back blade: + - slit center vs fixed aperture: given by the position of the edges + - beam center vs fixed aperture: given by the position of the bump in the middle """ - if setslit is None: - SetSlit1A(0.25,0.25,0,0) - #SetSlit1A(4.5,4.5,0,0,'q') - #SetSlit2B(6.0,8.0,0,0,'q') - if scanIOC is None: - scanIOC = BL_ioc() - VAL='29idb:Slit'+slit+'center.VAL' - RBV='29idb:Slit'+slit+'t2.D' - Scan_FillIn(VAL,RBV,scanIOC,scanDIM,start,stop,step) - Scan_Go(scanIOC,scanDIM=scanDIM,**kwargs) - + slit1A_set(0.25,0.25,0,0) + ID_SP_put(hv) + scan_slit_center('1H',-3,3,0.1) + scan_slit_center('1V',-3,3,0.1) + +def scan_slit_center(slit,start,stop,step,size=0.25): + """ + slit = '1H','1V','2H' or '2V' -def Scan_SlitSize(slit,start,stop,step,setslit=None,scanIOC=None,scanDIM=1,**kwargs): + Previously: Scan_SlitCenter """ - Scans the slit center: - slit='1H','1V','2H' or '2V' - Slit 1A is set to (1.75,1.75,0,0) unless setslit= not None - Logging is automatic: use **kwargs or the optional logging arguments see scanlog() for details - default: scanDIM=1 + if slit[0] == '1': + slit_name = "slit1A" + elif slit[0] == '2': + slit_name = "slit2B" + direction = slit[1] + slits_scan_center(slit_name,direction,start,stop,step,size=size) + + +def scan_slit_size(slit,start,stop,step,center=(0,0)): """ - if setslit is None: - SetSlit1A(1.75,1.75,0,0) #why is that? - #SetSlit1A(4.5,4.5,0,0,'q') # would open all the way? - #SetSlit2B(6.0,8.0,0,0,'q') - if scanIOC is None: - scanIOC = BL_ioc() - VAL='29idb:Slit'+slit+'size.VAL' - RBV='29idb:Slit'+slit+'t2.C' - Scan_FillIn(VAL,RBV,scanIOC,scanDIM,start,stop,step) - Scan_Go(scanIOC,scanDIM=scanDIM,**kwargs) + slit = '1H','1V','2H' or '2V' + Previously: Scan_SlitSize + """ + if slit[0] == '1': + slit_name = "slit1A" + elif slit[0] == '2': + slit_name = "slit2B" + direction = slit[1] + slits_scan_center(slit_name,direction,start,stop,step,center=center) - -def Check_ID_steering(hv=2000): - """ - Scans Slit1A center (set to a (0.25,0.25) pinhole) while looking at the back blade: - - slit center vs fixed aperture: given by the position of the edges - - beam center vs fixed aperture: given by the position of the bump in the middle - """ - SetSlit1A(0.25,0.25,0,0) - SetID_Raw(hv) - Scan_SlitCenter('1H',-3,3,0.1) - Scan_SlitCenter('1V',-3,3,0.1) - - ##################################################################################### # Checking the beam steering uses the gas-cell to see if the beam is centered on the grating # and that the slits are centered ##################################################################################### -def BeamProfile(GRT,SlitList,c_slit=1,c_energy=1,scanIOC=None,**kwargs): +def ID_beam_profile(grt,slit_list,c_slit=1,c_energy=1,**kwargs): """ Makes a nice 2D image of the energy distribution of the beam across the grating at ID=500 Does NOT put the diagnostics into the beam you need to run the following if you haven't already (AllDiagOut(); DiodeCIn()) @@ -771,53 +619,51 @@ def BeamProfile(GRT,SlitList,c_slit=1,c_energy=1,scanIOC=None,**kwargs): c_slit = scaling of step size (c=1 Slit-1: step = 0.25. Slit-2: step = 0.5) c_energy = scaling of mono step size ( c=1 eV step = 2) with c_slit=1 and c_energy = 1 Each slit ~ 1:10 min + + Previously """ - if scanIOC is None: - scanIOC=BL_ioc() - Switch_Grating(GRT) - GRT=caget("29idmono:GRT_DENSITY") - c=GRT/1200 + switch_gratings(grt) + grt_density = mono_grating_density_get() + c=grt_density/1200 ID=500 eVstart,eVstop,eVstep=460,540,4 - for slit in SlitList: + for slit in slit_list: if slit=="1H": #Hsize,Vsize,Hstart,Hstop,Hstep = 0.50,2,-2,2,0.25*c_slit # => 35 min #MonoVsSlit1AH_Go(ID,eVstart,eVstop,eVstep*c_energy,Hstart,Hstop,Hstep,Hsize,Vsize,scanIOC,**kwargs) - Scan_MonoVsSlit('1H',[0.5,-2,2,0.25*c_slit],[eVstart,eVstop,eVstep],comment='Mono/Slit - 1H') + scan_mono_vs_slit('1H',[0.5,-2,2,0.25*c_slit],[eVstart,eVstop,eVstep],comment='Mono/Slit - 1H') elif slit == "1V": #Hsize,Vsize,Vstart,Vstop,Vstep = 2,0.50,-2,2,0.25*c_slit #MonoVsSlit1AV_Go(ID,eVstart,eVstop,eVstep*c_energy,Vstart,Vstop,Vstep,Hsize,Vsize,scanIOC,**kwargs) - Scan_MonoVsSlit('1V',[0.5,-2,2,0.25*c_slit],[eVstart,eVstop,eVstep],comment='Mono/Slit - 1V') + scan_mono_vs_slit('1V',[0.5,-2,2,0.25*c_slit],[eVstart,eVstop,eVstep],comment='Mono/Slit - 1V') elif slit =="2H": #Hsize,Vsize,Hstart,Hstop,Hstep = 0.50,8,-3,3,0.5*c_slit #MonoVsSlit2BH_Go(ID,eVstart,eVstop,eVstep*c_energy,Hstart,Hstop,Hstep,Hsize,Vsize,scanIOC,**kwargs) - Scan_MonoVsSlit('2H',[0.5,-3,3,0.5*c_slit],[eVstart,eVstop,eVstep],comment='Mono/Slit - 2H') + scan_mono_vs_slit('2H',[0.5,-3,3,0.5*c_slit],[eVstart,eVstop,eVstep],comment='Mono/Slit - 2H') elif slit =="2V": #Hsize,Vsize,Vstart,Vstop,Vstep = 6,0.25*c,-4*c,4*c,0.5*c_slit #MonoVsSlit2BV_Go(ID,eVstart,eVstop,eVstep*c_energy,Vstart,Vstop,Vstep,Hsize,Vsize,scanIOC,**kwargs) - Scan_MonoVsSlit('2V',[0.5,-4,4,0.5*c_slit],[eVstart,eVstop,eVstep],comment='Mono/Slit - 2V') + scan_mono_vs_slit('2V',[0.5,-4,4,0.5*c_slit],[eVstart,eVstop,eVstep],comment='Mono/Slit - 2V') -def CheckAllSlits_long(hvList=[500],SlitList=["1H","1V","2H","2V"],scanIOC=None,**kwargs): +def CheckAllSlits_long(hv_list=[500],slit_list=["1H","1V","2H","2V"],**kwargs): """ For each photon energy in hvList, takes 3 slit curves @ mono below / resonance / above For given SlitList For both gratings """ - if scanIOC is None: - scanIOC=BL_ioc() - for GRT in ["HEG","MEG"]: # One full loop for a given grating and 3 energies takes 5h for average 20 - Switch_Grating(GRT) - for hv in hvList: - SetBL(hv) + for grt in ["HEG","MEG"]: # One full loop for a given grating and 3 energies takes 5h for average 20 + switch_gratings(grt) + for hv in hv_list: + slits_set_BL(hv) step=hv/100.0 start=hv-step stop=hv+step - for slit in SlitList: - for hv in RangeUp(start,stop,step): + for slit in slit_list: + for hv in range(start,stop,step): print("\r") - SetMono(hv) - CheckBeamPosition(slit,scanIOC,**kwargs) + mono_energy_set(hv) + check_ID_beam_steering(slit) def CheckSlitCalibration(slit_list,BL=500,hvList=[485,510],scanIOC=None,**kwargs): @@ -831,115 +677,47 @@ def CheckSlitCalibration(slit_list,BL=500,hvList=[485,510],scanIOC=None,**kwargs """ if scanIOC is None: scanIOC=BL_ioc() - SetExitSlit(50) - SetBL(BL) + exit_slit(50) + slits_set_BL(BL) for hv in hvList: - SetMono(hv) + mono_energy_set(hv) for slit in slit_list: - CheckBeamPosition(slit,scanIOC=scanIOC,**kwargs) + check_ID_beam_steering(slit) print("\n") -def CheckBeamPosition(slit,scanIOC=None,**kwargs): # instead of the full 2D map, you get 3 vertical cuts which - if scanIOC is None: - scanIOC=BL_ioc() - GRT=caget("29idmono:GRT_DENSITY") # can be plotted directly on dview using the buffer. That should - c=GRT/1200 # be fairly quick and not require any data loading/analysis - SetSlit1A(3.5,3.5,0,0,'q') - #SetSlit1A(4.5,4.5,0,0,'q') - SetSlit2B(6.0,8.0,0,0,'q') # Open up all the slits to make sure we scan the full beam +def check_ID_beam_steering(slit): #here + """ + checks the ID beam steering by scanning the slit with the ID detuned + if there is carbon on the mirror you might need to do the full ID_beam_profile to + find the red shifted beam + + slit = '1V','1H','2V','2H' + + Previously: CheckBeamPosition + """ + + grt_density = mono_grating_density_get() # can be plotted directly on dview using the buffer. That should + c=grt_density/1200 # be fairly quick and not require any data loading/analysis + + slit1A_set((3.5,3.5),(0,0),verbose=False) + slit2B_set((6.0,8.0),(0,0),verbose=False) # Open up all the slits to make sure we scan the full beam + if slit == "1H": -# size,start,stop,step = 0.50,-2.5,2.5,0.1 size,start,stop,step = 0.50,-4.5,4.5,0.2 elif slit == "1V": -# size,start,stop,step = 0.50,-2.5,2.5,0.1 size,start,stop,step = 0.50,-4.5,4.5,0.2 elif slit == "2H": -# size,start,stop,step = 0.25,-3.0,3.0,0.1 size,start,stop,step = 0.25,-8.0,8.0,0.2 elif slit == "2V": -# size,start,stop,step = 0.25,-3.5*c,3.5*c,0.1*c size,start,stop,step = 0.25*c,-4*c,4*c,0.2*c - VAL ="29idb:Slit"+slit+"center.VAL" - RBV ="29idb:Slit"+slit+"t2.D" - caput("29idb:Slit"+slit+"size.VAL",size) - print("\nScan "+slit+":") - scanIOC = BL_ioc() - scanDIM=1 - Scan_FillIn(VAL,RBV,scanIOC,scanDIM,start,stop,step) - Scan_Go(scanIOC,scanDIM,**kwargs) - SetSlit_BL(q='q') - - - - -def Reset_Slit2B_Encoders(Hcenter,Vcenter): - """ - Resetting Slit 2B encoders to 0 for a given position (Hcenter,Vcenter). - Slit size need to be set to 0. - """ - SetSlit2B(0,0,Hcenter,Vcenter) - print('\nCurrent Position:') - print(('e13 = '+str(caget('29idMini1:e13Pos')))) - print(('e14 = '+str(caget('29idMini1:e14Pos')))) - print(('e15 = '+str(caget('29idMini1:e15Pos')))) - print(('e16 = '+str(caget('29idMini1:e16Pos')))) - print('\nSetting all Offsets to 0:') - caput('29idMini1:e13Pos.EOFF',0) - caput('29idMini1:e14Pos.EOFF',0) - caput('29idMini1:e15Pos.EOFF',0) - caput('29idMini1:e16Pos.EOFF',0) - print('\nCurrent Position:') - print(('e13 = '+str(caget('29idMini1:e13Pos')))) - print(('e14 = '+str(caget('29idMini1:e14Pos')))) - print(('e15 = '+str(caget('29idMini1:e15Pos')))) - print(('e16 = '+str(caget('29idMini1:e16Pos')))) - print('\nSetting back Offsets:') - caput('29idMini1:e13Pos.EOFF',-caget('29idMini1:e13Pos')) - caput('29idMini1:e14Pos.EOFF',-caget('29idMini1:e14Pos')) - caput('29idMini1:e15Pos.EOFF',-caget('29idMini1:e15Pos')) - caput('29idMini1:e16Pos.EOFF',-caget('29idMini1:e16Pos')) - print('\nCurrent Position:') - print(('e13 = '+str(caget('29idMini1:e13Pos')))) - print(('e14 = '+str(caget('29idMini1:e14Pos')))) - print(('e15 = '+str(caget('29idMini1:e15Pos')))) - print(('e16 = '+str(caget('29idMini1:e16Pos')))) - Sync_Encoder_RBV('b') - SyncAllSlits() - -def Reset_Slit3D_Encoders(center): - """ - Resetting Slit 3D encoders to 0 for a given position (Hcenter,Vcenter). - Slit size need to be set to 0. - """ - caput('29idb:Slit4Vsize.VAL',0) - caput('29idb:Slit4Vcenter.VAL',center) - - print('\nCurrent Position:') - print(('e26 = '+str(caget('29idMini2:e26Pos')))) - print(('e27 = '+str(caget('29idMini2:e27Pos')))) - print('\nSetting all Offsets to 0:') - caput('29idMini2:e26Pos.EOFF',0) - caput('29idMini2:e27Pos.EOFF',0) - print('\nCurrent Position:') - print(('e26 = '+str(caget('29idMini2:e26Pos')))) - print(('e27 = '+str(caget('29idMini2:e27Pos')))) - print('\nSetting back Offsets:') - caput('29idMini2:e26Pos.EOFF',-caget('29idMini2:e26Pos')) - caput('29idMini2:e27Pos.EOFF',-caget('29idMini2:e27Pos')) - print('\nCurrent Position:') - print(('e26 = '+str(caget('29idMini2:e26Pos')))) - print(('e27 = '+str(caget('29idMini2:e27Pos')))) - Sync_Encoder_RBV('b') - SyncAllSlits() + scan_slit_center(slit,start,stop,step,size=size) + slits_set_BL() ############################################################################################################## ################## Commissioning paper curves ################## ############################################################################################################## - - - def FermiEdges(Energy,Slit): EF_Table={} EF_Table[500] = {10:20, 20:20, 50:20, 100:20, 200:20} @@ -951,8 +729,10 @@ def FermiEdges(Energy,Slit): -def QP_Curves(hv,list_mode,start,stop,step): - SetExitSlit(200) +def QP_curves(ID_energy,ID_mode_list,hv_start,hv_stop,hv_step): + """ + """ + exit_slit(200) #Switch_Grating("MEG") #print "\r" #print "**************** QP OFF ****************" @@ -966,13 +746,13 @@ def QP_Curves(hv,list_mode,start,stop,step): #print "\r" #print "**************** QP ON ****************" #Switch_IDQP("on") - for mode in list_mode: - Switch_IDMode(mode) - SetID_Raw(hv) - SetSlit_BL() - SetMono(250) - Scan_Mono(1,start,stop,step) - Scan_Go("b",scanDIM=1) + for ID_mode in ID_mode_list: + polarization(ID_mode) + ID_SP_put(ID_energy) + slits_set_BL()() + mono_energy_set(250) + mono_scan_fillin(hv_start,hv_stop,hv_step) + BL.mda.go() #Switch_IDQP("off") #Switch_Grating("HEG") #Switch_IDMode("RCP") @@ -984,7 +764,7 @@ def QP_Curves(hv,list_mode,start,stop,step): ###### Energy range follows ID ######## -def IDCalibration_Scan(start,stop,step,bandwidth=10,QP=None,Harm=1,scanIOC=None): +def ID_calibration_scan(start,stop,step,bandwidth=10,QP=None,Harm=1,scanIOC=None): """ Sets the ID_SP and scans the mono: start,stop,step are for ID @@ -1014,7 +794,7 @@ def IDCalibration_Scan(start,stop,step,bandwidth=10,QP=None,Harm=1,scanIOC=None) elif c == 2: maxhv = 2000 kwargs={'comment': "====== Starting Mono Scan vs ID"} kwargs.update({'FileSuffix': "IDCalibration"}) - logprint(**kwargs) + log_print(**kwargs) for ID in RangeUp(start,stop,step): print("\n------------------ ID-SP @ "+str(ID)+" ------------------") SetMono(ID)