Sprint 12/21

This commit is contained in:
gac-x11ma
2020-12-09 15:06:55 +01:00
parent 13352381ed
commit b0718601c2
19 changed files with 1717 additions and 682 deletions
+97 -16
View File
@@ -5,8 +5,9 @@ import ch.psi.pshell.imaging.Pen as Pen
import java.awt.Rectangle as Rectangle
import ch.psi.pshell.imaging.Data as Data
import ch.psi.pshell.device.Camera.DataType as DataType
import ch.psi.utils.Chrono as Chrono
CONTINOUS_MODE_MIN_TIME = 4000
###############################################################################
# ROI Integration
###############################################################################
@@ -179,31 +180,111 @@ def trigger_eiger(wait=False):
if wait:
eiger.waitNewImage(20000)
def set_exposure_time(exposure):
if exposure == eiger.getExposure():
return
def get_eiger_exposure_readback():
return caget("X11MA-ES1-SD1:cam1:AcquireTime_RBV",'f')
def set_exposure_time(value, check = True, retries=3):
if value == eiger.getExposure():
return
started = eiger.isStarted()
if started:
eiger.stop()
time.sleep(0.2)
eiger.setExposure(exposure)
stop_eiger()
for i in range(retries):
try:
eiger.setExposure(value)
if check:
readback=get_eiger_exposure_readback()
if abs(value - readback) > 0.01:
raise Exception("Error changing Eiger exposure time to %f: readback=%f" % (value, readback))
except:
if i==(retries-1):
raise
else:
print "Error changing Eiger exposure time: retrying"
time.sleep(0.3)
if started:
if eiger.grabMode==eiger.GrabMode.Continuous:
eiger.start()
def get_eiger_number_of_frames():
return caget("X11MA-ES1-SD1:cam1:NumFrames_RBV",'i')
def restore_eiger():
def set_eiger_number_of_frames(value, check = True):
if value == get_eiger_number_of_frames():
return
started = eiger.isStarted()
if started:
stop_eiger()
caput("X11MA-ES1-SD1:cam1:NumFrames",value)
if check:
readback = get_eiger_number_of_frames()
if value != readback:
raise Exception("Error changing Eiger number of frames to %d: readback=%d" % (value, readback))
if started:
if eiger.grabMode==eiger.GrabMode.Continuous:
eiger.start()
#Wait for channel to chenge
def stop_eiger():
global chrono_eiger
chrono_eiger.waitTimeout(CONTINOUS_MODE_MIN_TIME)
started = eiger.isStarted()
if started:
eiger.stop()
eiger.grabMode=eiger.GrabMode.Single
eiger.stop()
time.sleep(0.3)
if eiger.acquire.read() >0:
raise Exception("Error stopping Eiger")
chrono_eiger = Chrono()
def init_eiger(exposure=None, check=True, retries=2):
"""
Set Eiger scan mode
"""
global chrono_eiger
chrono_eiger.waitTimeout(CONTINOUS_MODE_MIN_TIME)
for i in range(retries):
try:
stop_eiger() #Set mode single
eiger.setNumImages(1)# Is it relevant?
set_eiger_number_of_frames(1)
if exposure:
set_exposure_time(exposure, check)
break
except:
if i==(retries-1):
raise
else:
print "Error initializing Eiger, retrying: " + str(sys.exc_info()[1])
def restore_eiger(check=True, retries=2):
"""
Set Eiger default mode
"""
if eiger.isStarted():
eiger.stop()
time.sleep(0.2)
eiger.grabMode=eiger.GrabMode.Continuous
eiger.setExposure(0.2)
eiger.setNumImages(1)
eiger.start()
global chrono_eiger
for i in range(retries):
try:
stop_eiger()
eiger.setNumImages(1)# Is it relevant?
set_eiger_number_of_frames(1, check)
set_exposure_time(0.2, check)
eiger.grabMode=eiger.GrabMode.Continuous
eiger.start()
chrono_eiger = Chrono()
break
except:
if i==(retries-1):
raise
else:
print "Error restoring Eiger, retrying " + str(sys.exc_info()[1])
_outliers_mask_timestamp = 0
_outliers_mask = None
+96 -6
View File
@@ -96,17 +96,20 @@ def put_id_pol(id, pol, alpha=None):
elif pol == 2:
mode_dev.write("CIRC -")
elif pol == 3:
mode_dev.write("LINEAR")
time.sleep(0.5)
if mode_dev.read() != "LINEAR":
mode_dev.write("LINEAR")
time.sleep(0.5)
alpha_dev.write(0)
elif pol == 4:
mode_dev.write("LINEAR")
time.sleep(0.5)
if mode_dev.read() != "LINEAR":
mode_dev.write("LINEAR")
time.sleep(0.5)
alpha_dev.write(90)
elif pol == 5:
mode_dev.write("LINEAR")
if alpha is not None:
if mode_dev.read() != "LINEAR":
mode_dev.write("LINEAR")
time.sleep(0.5)
if alpha is not None:
alpha_dev.write(alpha)
@@ -153,3 +156,90 @@ class EnOptDesc(ReadonlyRegisterBase):
add_device(EnOptDesc(), True)
energy_opt_desc.setPolling(2000)
#Polarizarion Switch Tools
_switching_type = None
_switching_active_id = None
_switching_current_pol = None
_switching_pol_id1 = None
_switching_pol_id2 = None
_switching_id = None
def init_pol_switch(switching_type, sid = None, pol_id1=None, pol_id2=None):
global _switching_type, _switching_active_id, _switching_current_pol, _switching_pol_id1, _switching_pol_id2, _switching_id
if sid is None:
sid = get_setting("ID")
if pol_id1 is None:
#pol_id1 = POL_IDS[get_setting("POL_ID_1")] #From config
pol_id1=get_id_pol(1) #Current
if pol_id2 is None:
#pol_id2 =POL_IDS[get_setting("POL_ID_2")] #From config
pol_id2 =get_id_pol(2) #Current
_switching_type = switching_type
_switching_id =sid
_switching_pol_id1=pol_id1
_switching_pol_id2=pol_id2
print "Init pol switch: %s id:%s pol_id1:%s pol_id2:%s" %(_switching_type, _switching_id, _switching_pol_id1, _switching_pol_id2)
_switching_active_id = 1
if _switching_id == "ID1":
_switching_current_pol = _switching_pol_id1
elif _switching_id == "ID2":
_switching_current_pol = _switching_pol_id2
elif _switching_id == "ID1_ID2":
_switching_current_pol=_switching_pol_id1
if switching_type == "Tune_Detune":
tune_detune(1) #Tune ID1, Detune ID2
else:
if _switching_id == "ID1_ID2":
put_id_pol(2, _switching_current_pol) #Force both IDs to same polarization
wait_channel("X11PHS:alldone", 1)
def nextpol():
global _switching_type, _switching_active_id, _switching_current_pol, _switching_pol_id1, _switching_pol_id2
if _switching_type == "Normal":
if _switching_current_pol==1: return 2 #circ+ -> circ-
elif _switching_current_pol==2: return 1 #circ+ -> circ-
elif _switching_current_pol==3: return 4 #lin hor -> lin vert
elif _switching_current_pol==4: return 3 #lin vert -> lin hor
elif _switching_current_pol==5: return5 #lin rot -> lin rot
else: raise "Invalid pol: " + str(_switching_current_pol)
elif _switching_type == "Tune_Detune":
if _switching_active_id==1: return _switching_pol_id2
elif _switching_active_id==2: return _switching_pol_id1
else: raise "Invalid ID: " + str(_switching_active_id)
else: raise "Invalid switching: " + str(_switching_type)
def switch_pol():
global _switching_type, _switching_active_id, _switching_current_pol, _switching_pol_id1, _switching_pol_id2, _switching_id
if DRY_RUN:
return
newpol=nextpol()
print "Switch pol: ", newpol
if _switching_id == "ID1":
put_id_pol(1,newpol)
elif _switching_id == "ID2":
put_id_pol(2,newpol)
elif ID == "ID1_ID2":
if _switching_type == "Normal":
put_id_pol(1, newpol)
put_id_pol(2, newpol)
elif _switching_type == "Tune_Detune":
if _switching_active_id==1:
_switching_active_id=2
else:
_switching_active_id=1
tune_detune(_switching_active_id)
if _switching_type == "Normal":
_switching_current_pol = newpol
time.sleep(1.0)
wait_channel("X11PHS:alldone", 1)
def get_cur_pol():
return _switching_current_pol
+83 -3
View File
@@ -409,7 +409,7 @@ def write_logfile(msg):
"""
def put_energy(v):
if DRY_RUN: return
if get_dry_run(): return
if v>91 and v<2500:
caput("X11PHS:alldone",0)
caput("X11PHS-E:GO.A",v)
@@ -423,7 +423,7 @@ def is_done():
return True if caget("X11PHS:alldone") else False
def wait_done():
if DRY_RUN: return
if get_dry_run(): return
time.sleep(1.0) #in order to reduce trafic on the IOC
wait_channel("X11PHS:alldone", 1)
"""
@@ -434,6 +434,13 @@ def put_energy(v):
wait_channel(ALL_DONE, 1, type = 'i')
def change_energy(v):
if v<91 or v>2500:
raise Exception ("Invalid energy: " + str(v))
if DRY_RUN:
return
put_energy(v)
###################################################################################################
#Image measurements
###################################################################################################
@@ -560,7 +567,80 @@ def play_sound(name):
Audio.playFile(File(get_context().setup.expandPath("{home}/sounds/" + name + ".wav")), False)
except:
log("Error playing sound " + name + ": " + str(sys.exc_info()[1]), False)
###################################################################################################
#Beamline setup
###################################################################################################
def apply_beamline_setup(ID,ENERGY,POL_ID_1,ALPHA_ID_1,HARMONIC_ID_1,OFFSET_ID_1,POL_ID_2,ALPHA_ID_2,HARMONIC_ID_2,OFFSET_ID_2):
if get_dry_run():
return
if ID=='ID1':
caput('X11PHS-E:OPT',1)
elif ID=='ID2':
caput('X11PHS-E:OPT',2)
elif ID =='ID1_ID2':
caput('X11PHS-E:OPT',3)
if ID == "ID1":
#current_pol=POL_IDS[POL_ID_1] #get_id_pol(1)
put_id_pol(1,POL_ID_1, ALPHA_ID_1 if (POL_ID_1=="Lin") else None )
caput('X11MA-ID2-GAP:SET',100) #open Gap ID2
id1_harmonic.write(int(HARMONIC_ID_1))
put_id_offset(1, float(OFFSET_ID_1)) #offset on ID1
elif ID == "ID2":
#current_pol=POL_IDS[POL_ID_2]#get_id_pol(2)
put_id_pol(2,POL_ID_2, ALPHA_ID_2 if (POL_ID_2=="Lin") else None )
caput('X11MA-ID1-GAP:SET',100) #open Gap ID1
id2_harmonic.write(int(HARMONIC_ID_2))
put_id_offset(2, float(OFFSET_ID_2)) #offset on ID2
elif ID == "ID1_ID2":
#polID1=POL_IDS[POL_ID_1]
#polID2=POL_IDS[POL_ID_2]
put_id_pol(1,POL_ID_1, ALPHA_ID_1 if (POL_ID_1=="Lin") else None )
put_id_pol(2,POL_ID_2, ALPHA_ID_2 if (POL_ID_2=="Lin") else None )
#current_pol=polID1
id1_harmonic.write(int(HARMONIC_ID_1))
id2_harmonic.write(int(HARMONIC_ID_2))
put_id_offset(1, float(OFFSET_ID_1)) #offset on ID1
put_id_offset(2, float(OFFSET_ID_2)) #offset on ID2
#wait_channel("X11PHS:alldone", 1)
energy.write(ENERGY)
wait_channel("X11PHS:alldone", 1)
def set_beamline_setup(ID,ENERGY,POL_ID_1,ALPHA_ID_1,HARMONIC_ID_1,OFFSET_ID_1,POL_ID_2,ALPHA_ID_2,HARMONIC_ID_2,OFFSET_ID_2):
set_setting("ID", ID)
set_setting("ENERGY", ENERGY)
set_setting("POL_ID_1", POL_ID_1)
set_setting("ALPHA_ID_1", ALPHA_ID_1)
set_setting("HARMONIC_ID_1", HARMONIC_ID_1)
set_setting("OFFSET_ID_1", OFFSET_ID_1)
set_setting("POL_ID_2", POL_ID_2)
set_setting("ALPHA_ID_2", ALPHA_ID_2)
set_setting("HARMONIC_ID_2", HARMONIC_ID_2)
set_setting("OFFSET_ID_2", OFFSET_ID_2)
apply_beamline_setup(ID,ENERGY,POL_ID_1,ALPHA_ID_1,HARMONIC_ID_1,OFFSET_ID_1,POL_ID_2,ALPHA_ID_2,HARMONIC_ID_2,OFFSET_ID_2)
#Restore beamline initial config
def restore_beamline_setup():
ID = get_setting("ID")
ENERGY = float(get_setting("ENERGY"))
POL_ID_1 = get_setting("POL_ID_1")
ALPHA_ID_1 = float(get_setting("ALPHA_ID_1"))
HARMONIC_ID_1 = get_setting("HARMONIC_ID_1")
OFFSET_ID_1 = float(get_setting("OFFSET_ID_1"))
POL_ID_2 = get_setting("POL_ID_2")
ALPHA_ID_2 = float(get_setting("ALPHA_ID_2"))
HARMONIC_ID_2 = get_setting("HARMONIC_ID_2")
OFFSET_ID_2 = float(get_setting("OFFSET_ID_2"))
apply_beamline_setup(ID,ENERGY,POL_ID_1,ALPHA_ID_1,HARMONIC_ID_1,OFFSET_ID_1,POL_ID_2,ALPHA_ID_2,HARMONIC_ID_2,OFFSET_ID_2)
###################################################################################################
#Settings
###################################################################################################
+9 -73
View File
@@ -13,11 +13,11 @@ if get_exec_pars().source == CommandSource.ui:
AVERAGE_2 = 2.0
ENERGY_2= 900.0
#POLARIZATION_2 = "Circ_Minus"
DRY_RUN = get_dry_run()
SHOW_IMAGES = True
SHOW_IMAGES = True
SAVE_DIAGS = False
ID = get_setting("ID")
@@ -98,78 +98,14 @@ def assert_status_ok():
#Initialize vartiables
if not DRY_RUN and str(get_setting("AUTO_SWITCH_VALVE")).lower() == "true":
open_vg10()
active_id = 1
current_pol=None
pol_id1=POL_IDS[get_setting("POL_ID_1")]
pol_id2=POL_IDS[get_setting("POL_ID_2")]
#rbkEnergy=energy_rbk.read()
if METHOD == "Two_Pol":
if ID == "ID1":
current_pol = pol_id1
elif ID == "ID2":
current_pol = pol_id2
elif ID == "ID1_ID2":
current_pol=pol_id1
if SWITCHING == "Tune_Detune":
tune_detune(1) #Tune ID1, Detune ID2
else:
if ID == "ID1_ID2":
put_id_pol(2, current_pol) #Force both IDs to same polarization
if METHOD == "Two_Pol":
init_pol_switch(SWITCHING)
def imageinfo(info):
pass
#Beamline setting
def nextpol():
global current_pol, pol_id1, pol_id2, active_id
if SWITCHING == "Normal":
if current_pol==1: return 2 #circ+ -> circ-
if current_pol==2: return 1 #circ+ -> circ-
if current_pol==3: return 4 #lin hor -> lin vert
if current_pol==4: return 3 #lin vert -> lin hor
if current_pol==5: return 5 #lin rot -> lin rot
elif SWITCHING == "Tune_Detune":
if active_id==1: return pol_id2
if active_id==2: return pol_id1
def switch_pol():
global active_id
if DRY_RUN:
return
newpol=nextpol()
if ID == "ID1":
put_id_pol(1,newpol)
elif ID == "ID2":
put_id_pol(2,newpol)
elif ID == "ID1_ID2":
if SWITCHING == "Normal":
put_id_pol(1, newpol)
put_id_pol(2, newpol)
elif SWITCHING == "Tune_Detune":
if active_id==1:
active_id=2
else:
active_id=1
tune_detune(active_id)
time.sleep(1.0)
wait_channel("X11PHS:alldone", 1)
def change_energy(v):
if v<91 or v>2500:
raise Exception ("Invalid energy: " + str(v))
if DRY_RUN:
return
put_energy(v)
def save_image_file(frame, cycle=-1, frame_index=0):
if SHOW_IMAGES:
@@ -181,10 +117,8 @@ def save_image_file(frame, cycle=-1, frame_index=0):
log(filename)
print filename
# log("SV:"+Format(startvoltage,"0.000")+" OB:"+Format(objective,"0.00")+" ST:"+Format(LEEMtemp,"0.0"))
eiger.stop()
eiger.grabMode=eiger.GrabMode.Single
time.sleep(0.3)
init_eiger()
#print "Startup time: " + str(time.time() - start)
try:
#Do the measurement loop
@@ -201,7 +135,9 @@ try:
if (cycle == 1) or (METHOD != "Take_Image"):
assert_status_ok()
set_exposure_time(EXPOSURE[i])
print "--- Grabing " + str(AVERAGE[i])+ " frames - cycle: " + str(cycle) + " step: " + str(i)
#s=time.time()
ret = grab_frames(image, AVERAGE[i], roi=None, wait_next=True)
#print "--- Time: " + str(time.time() - s)
frames.append(average_frames(ret) if AVERAGE[i] > 1 else ret[0])
imageinfo("I")
@@ -218,8 +154,8 @@ try:
print "--- Switching energy..."
change_energy(ENERGY_2)
#time.sleep(1)
if (METHOD == "Two_Pol") or (METHOD == "Two_Energies"):
if (METHOD == "Two_Pol") or (METHOD == "Two_Energies"):
if (METHOD == "Two_Energies") or (get_cur_pol() in (2,3)):
###??? autocontrast???
frames.append(frames[0].copy())
+13 -7
View File
@@ -13,6 +13,10 @@ if get_exec_pars().source == CommandSource.ui:
DRY_RUN = get_dry_run()
SAVE_DIAGS = True
if SWITCH_POL:
init_pol_switch("Normal")
log("ROIs: " + str(ROI))
if len(RANGES) == 0:
@@ -20,10 +24,7 @@ if len(RANGES) == 0:
start = time.time()
eiger.stop()
eiger.grabMode=eiger.GrabMode.Single
time.sleep(0.3)
set_exposure_time(EXPOSURE)
init_eiger(exposure=EXPOSURE)
#set_exec_pars(path="{data}/{year}_{month}/{date}/{seq}%03d_AbsortionSpectrum", format="csv", layout="table")
set_exec_pars(name="AbsortionSpectrum", format="csv", layout="table")
@@ -88,7 +89,6 @@ if not DRY_RUN and str(get_setting("AUTO_SWITCH_VALVE")).lower() == "true":
#put_id_offset(2, OFFSET_ID_2) #offset on ID2
"""
if ID == "ID1":
current_pol=POL_IDS[POL_ID_1] #get_id_pol(1)
@@ -106,10 +106,16 @@ elif ID == "ID1_ID2":
put_id_pol(2,polID2)
wait_channel("X11PHS:alldone", 1)
"""
def after_pass(pass_number, scan):
if SWITCH_POL:
if pass_number<scan.numberOfPasses:
switch_pol()
try:
#tscan(rois, 10, 0.1, format="csv", before_read=grab_image, passes = NUMBER_SCANS, tag=tag)
rscan(sync_energy, sensors, RANGES, latency = 0.0 , passes = NUMBER_SCANS, tag=tag, before_read=grab_image, save=SAVE_SPECTRUM, split=True, keep=False)
rscan(sync_energy, sensors, RANGES, latency = 0.0 , passes = NUMBER_SCANS, tag=tag, before_read=grab_image, save=SAVE_SPECTRUM, split=True, keep=False, after_pass=after_pass)
finally:
if AVERAGE>1:
for i in range(len(rois)):
+1 -60
View File
@@ -11,63 +11,4 @@ if get_exec_pars().source == CommandSource.ui:
HARMONIC_ID_2 = 1
OFFSET_ID_2 = 0.0
DRY_RUN = get_dry_run()
set_setting("ID", ID)
set_setting("ENERGY", ENERGY)
set_setting("POL_ID_1", POL_ID_1)
set_setting("ALPHA_ID_1", ALPHA_ID_1)
set_setting("HARMONIC_ID_1", HARMONIC_ID_1)
set_setting("OFFSET_ID_1", OFFSET_ID_1)
set_setting("POL_ID_2", POL_ID_2)
set_setting("ALPHA_ID_2", ALPHA_ID_2)
set_setting("HARMONIC_ID_2", HARMONIC_ID_2)
set_setting("OFFSET_ID_2", OFFSET_ID_2)
if DRY_RUN:
abort()
if ID=='ID1':
caput('X11PHS-E:OPT',1)
elif ID=='ID2':
caput('X11PHS-E:OPT',2)
elif ID =='ID1_ID2':
caput('X11PHS-E:OPT',3)
if ID == "ID1":
#current_pol=POL_IDS[POL_ID_1] #get_id_pol(1)
put_id_pol(1,POL_ID_1, ALPHA_ID_1 if (POL_ID_1=="Lin") else None )
caput('X11MA-ID2-GAP:SET',100) #open Gap ID2
id1_harmonic.write(int(HARMONIC_ID_1))
put_id_offset(1, float(OFFSET_ID_1)) #offset on ID1
elif ID == "ID2":
#current_pol=POL_IDS[POL_ID_2]#get_id_pol(2)
put_id_pol(2,POL_ID_2, ALPHA_ID_2 if (POL_ID_2=="Lin") else None )
caput('X11MA-ID1-GAP:SET',100) #open Gap ID1
id2_harmonic.write(int(HARMONIC_ID_2))
put_id_offset(2, float(OFFSET_ID_2)) #offset on ID2
elif ID == "ID1_ID2":
#polID1=POL_IDS[POL_ID_1]
#polID2=POL_IDS[POL_ID_2]
put_id_pol(1,POL_ID_1, ALPHA_ID_1 if (POL_ID_1=="Lin") else None )
put_id_pol(2,POL_ID_2, ALPHA_ID_2 if (POL_ID_2=="Lin") else None )
#current_pol=polID1
id1_harmonic.write(int(HARMONIC_ID_1))
id2_harmonic.write(int(HARMONIC_ID_2))
put_id_offset(1, float(OFFSET_ID_1)) #offset on ID1
put_id_offset(2, float(OFFSET_ID_2)) #offset on ID2
#wait_channel("X11PHS:alldone", 1)
energy.write(ENERGY)
wait_channel("X11PHS:alldone", 1)
set_beamline_setup(ID,ENERGY,POL_ID_1,ALPHA_ID_1,HARMONIC_ID_1,OFFSET_ID_1,POL_ID_2,ALPHA_ID_2,HARMONIC_ID_2,OFFSET_ID_2)