added automatic threaded upload of the run_table to gsheet, whenever a position is recorded

This commit is contained in:
2020-11-13 16:16:49 +01:00
parent 4107949d9c
commit 6efb6e38c7
6 changed files with 285 additions and 56 deletions
+18
View File
@@ -3,4 +3,22 @@ import sys
from .config import config
# {
# "name": "elog",
# "type": "eco.utilities.elog:Elog",
# "args": ["https://elog-gfa.psi.ch/Bernina"],
# "kwargs": {
# "screenshot_directory": "/tmp",
# },
# },
@init_obj(lazy=is_globally_lazy)
def init_specific_device(*args,**kwargs):
from whatever import something
return something(*args,**kwargs)
specific_name = init_specific_device(name=specific_name)
+12 -12
View File
@@ -51,7 +51,7 @@ components = [
"alias_namespace": None,
"channels_ca": Component("_env_channels_ca"),
},
"lazy": False,
"lazy": True,
},
{
"type": "eco.elements.memory:set_global_memory_dir",
@@ -359,15 +359,15 @@ components = [
"type": "eco.xoptics.KBhor:KBhor",
"kwargs": {},
},
{
"name": "spatial_tt",
"args": [],
"kwargs": {"reduction_client_address": "http://sf-daqsync-02:12003/"},
"z_und": 141,
"desc": "spatial encoding timing diagnostics before sample.",
"type": "eco.xdiagnostics.timetools:SpatialEncoder",
"lazy": False,
},
# {
# "name": "spatial_tt",
# "args": [],
# "kwargs": {"reduction_client_address": "http://sf-daqsync-02:12003/"},
# "z_und": 141,
# "desc": "spatial encoding timing diagnostics before sample.",
# "type": "eco.xdiagnostics.timetools:SpatialEncoder",
# "lazy": True,
# },
# {
# "name": "slit_kb",
# "args": [],
@@ -388,7 +388,7 @@ components = [
"configuration": config["gps_config"],
"fina_hex_angle_offset": "~/eco/reference_values/hex_pi_angle_offset.json",
},
"lazy": False,
"lazy": True,
},
{
"args": [],
@@ -409,7 +409,7 @@ components = [
"configuration": config["xrd_config"],
"diff_detector": {"jf_id": "JF01T03V01"},
},
"lazy": False,
"lazy": True,
},
{
"args": [],
+5 -3
View File
@@ -22,7 +22,9 @@ class Jungfrau(Assembly):
self.memory = memory.Memory(self)
self.jf_id = jf_id
self._append(PvRecord, pv_trigger, is_status=True, name="trigger")
self._append(
PvRecord, pv_trigger, is_status=True, is_setting=False, name="trigger"
)
self._trigger_on = trigger_on
self._trigger_off = trigger_off
self._append(
@@ -32,11 +34,11 @@ class Jungfrau(Assembly):
self._set_trigger_enable,
name="trigger_enable",
append_aliases=False,
is_setting=True,
is_setting=False,
)
def _set_trigger_enable(self, value):
if value:
self.trigger.set_target_value(self._trigger_on).wait()
else:
self.trigger.set_target_value(self._triggeroff).wait()
self.trigger.set_target_value(self._trigger_off).wait()
+26 -2
View File
@@ -89,6 +89,18 @@ class GPS:
return self.get_adjustable_positions_str()
class DeltaTauCurrOff:
def __init__(self, pvname, name=None):
self.pvname = pvname
self.PV = PV(pvname)
def set_off(self):
self.PV.put("#1..8k")
def __call__(self):
self.set_off()
class XRD(Assembly):
def __init__(self, name=None, Id=None, configuration=["base"], diff_detector=None):
"""X-ray diffractometer platform in AiwssFEL Bernina.\
@@ -109,6 +121,7 @@ class XRD(Assembly):
self._append(
MotorRecord_new, Id + ":MOT_MY_RYTH", name="alpha", is_setting=True
)
self.set_base_off = DeltaTauCurrOff("SARES21-XRD:asyn4.AOUT")
if "arm" in self.configuration:
### motors XRD detector arm ###
@@ -124,6 +137,7 @@ class XRD(Assembly):
### motors XRD polarisation analyzer branch ###
self._append(MotorRecord_new, Id + ":MOT_P_T", name="tpol", is_setting=True)
# missing: slits of flight tube
self.set_detarm_off = DeltaTauCurrOff("SARES21-XRD:asyn3.AOUT")
if "hlxz" in self.configuration:
### motors heavy load goniometer ###
@@ -133,10 +147,12 @@ class XRD(Assembly):
self._append(
MotorRecord_new, Id + ":MOT_TBL_TZ", name="zhl", is_setting=True
)
self.set_phi_off = DeltaTauCurrOff("SARES21-XRD:asyn1.AOUT")
if "hly" in self.configuration:
self._append(
MotorRecord_new, Id + ":MOT_TBL_TY", name="yhl", is_setting=True
)
self.set_phi_off = DeltaTauCurrOff("SARES21-XRD:asyn1.AOUT")
if "hlrxrz" in self.configuration:
try:
@@ -152,7 +168,7 @@ class XRD(Assembly):
)
except:
print("XRD.rzhl not found")
pass
self.set_phi_off = DeltaTauCurrOff("SARES21-XRD:asyn1.AOUT")
if "phi_table" in self.configuration:
### motors nu table ###
@@ -242,8 +258,16 @@ class XRD(Assembly):
name="rykap",
is_setting=True,
)
self.set_kappa_off = DeltaTauCurrOff("SARES21-XRD:asyn1.AOUT")
if diff_detector:
self._append(Jungfrau, diff_detector["jf_id"], name="det_diff")
self._append(
Jungfrau,
diff_detector["jf_id"],
name="det_diff",
is_setting=False,
is_status=True,
view_toplevel_only=True,
)
def get_adjustable_positions_str(self):
ostr = "*****XRD motor positions******\n"
+16 -2
View File
@@ -16,6 +16,8 @@ import xlwt
import openpyxl
from ..devices_general.pv_adjustable import PvRecord
from epics import caget
import threading
class Run_Table():
def __init__(self, pgroup=None,spreadsheet_key=None, devices=None, alias_namespace=None, channels_ca={'pulse_id': 'SLAAR11-LTIM01-EVR0:RX-PULSEID'}, name=None):
@@ -147,8 +149,8 @@ class Run_Table():
multiindex_u = pd.MultiIndex.from_tuples([(dev, adj) for dev in self.units.keys() for adj in self.units[dev].keys()], names=names)
values_u = np.array([val for adjs in self.units.values() for val in adjs.values()])
self.unit_df = DataFrame([values_u], columns=multiindex_u, index=['units'])
self.save()
self.save()
self.upload_all()
def append_pos(self, name=''):
self.load()
@@ -175,6 +177,7 @@ class Run_Table():
values_u = np.array([val for adjs in self.units.values() for val in adjs.values()])
self.unit_df = DataFrame([values_u], columns=multiindex_u, index=['units'])
self.save()
self.upload_all()
def upload_rt(self, worksheet='runtable', keys=None, df=None):
'''
@@ -222,6 +225,17 @@ class Run_Table():
gd.set_with_dataframe(self.ws, upload_df, include_index=True, col=2)
gf_dataframe.format_with_dataframe(self.ws, upload_df, include_index=True, include_column_header=True, col=2)
def _upload_all(self):
try:
self.upload_rt()
self.upload_pos()
except:
print(f'Uploading of runtable to gsheet https://docs.google.com/spreadsheets/d/{self._spreadsheet_key}/ failed. Run run_table.upload_rt() for error traceback')
def upload_all(self):
rt = threading.Thread(target=self._upload_all)
rt.start()
def _orderlist(self, mylist, key_order, orderlist=None):
key_order = key_order.split(' ')
+208 -37
View File
@@ -1,8 +1,24 @@
import numpy as np
from scipy import constants
from ..elements import Assembly
from ..devices_general.motors import MotorRecord
from ..devices_general.adjustable import PvRecord
class KBMirrorBernina:
def __init__(self,kb_ver=None, kb_hor=None, usd_table=None, d_kbver=3350.,d_kbhor=2600.,d_hex=1600.,d_win1=1945.,d_win2=1330.,d_target=1520.,d_att=1420.):
def __init__(
self,
kb_ver=None,
kb_hor=None,
usd_table=None,
d_kbver=3350.0,
d_kbhor=2600.0,
d_hex=1600.0,
d_win1=1945.0,
d_win2=1330.0,
d_target=1520.0,
d_att=1420.0,
):
"""All distances are from sample interaction point at straight beam (no kb deflection), the units are expected in mm"""
self.kb_ver = kb_ver
self.kb_hor = kb_hor
@@ -15,62 +31,217 @@ class KBMirrorBernina:
self.d_win1 = d_win1
self.d_target = d_target
def calc_positions(self,the_kbver,the_kbhor):
def calc_positions(self, the_kbver, the_kbhor):
"""angles in rad"""
y_kbhor = np.tan(2*the_kbver) * np.abs(self.d_kbver-self.d_kbhor)
rx_kbhor = -2 * the_kbver
y_hex = np.tan(2*the_kbver) * np.abs(self.d_kbver-self.d_hex)
x_hex = np.tan(2*the_kbhor) * np.abs(self.d_kbhor-self.d_hex)
y_kbhor = np.tan(2 * the_kbver) * np.abs(self.d_kbver - self.d_kbhor)
rx_kbhor = -2 * the_kbver
y_hex = np.tan(2 * the_kbver) * np.abs(self.d_kbver - self.d_hex)
x_hex = np.tan(2 * the_kbhor) * np.abs(self.d_kbhor - self.d_hex)
rx_hex = rx_kbhor
ry_hex = 2* the_kbhor
return {'y_kbhor':y_kbhor,'rx_kbhor':rx_kbhor,'x_hex':x_hex,'y_hex':y_hex,'rx_hex':rx_hex,'ry_hex':ry_hex}
ry_hex = 2 * the_kbhor
return {
"y_kbhor": y_kbhor,
"rx_kbhor": rx_kbhor,
"x_hex": x_hex,
"y_hex": y_hex,
"rx_hex": rx_hex,
"ry_hex": ry_hex,
}
def calc_fwhm(self,fwhm_hor,fwhm_ver,z_focver=0,z_fochor=0,E_phot=None):
def calc_fwhm(self, fwhm_hor, fwhm_ver, z_focver=0, z_fochor=0, E_phot=None):
""" E_phot in eV, length units in mm."""
lam = constants.c*constants.h/constants.electron_volt /E_phot
print(lam*1e10)
fwhm_fac = 1/np.sqrt(2*np.log(2))# w = fwhm_fac*fwhm
lam = constants.c * constants.h / constants.electron_volt / E_phot
print(lam * 1e10)
fwhm_fac = 1 / np.sqrt(2 * np.log(2)) # w = fwhm_fac*fwhm
# div_ver = np.arctan(fwhm_ver*fwhm_fac/2/(self.d_kbver+z_focver)) #half divergence
# div_hor = np.arctan(fwhm_hor*fwhm_fac/2/(self.d_kbhor+z_fochor))
c = lam/np.pi*1e3
c = lam / np.pi * 1e3
w0 = lambda w,z:( w**2 - ( w**4 - (2*c*z)**2 )**0.5)**0.5/np.sqrt(2)
w = lambda w0,z: (w0**2+(c*z/w0)**2)**0.5
zr = lambda w0: w0**2/c
w0 = lambda w, z: (
w ** 2 - (w ** 4 - (2 * c * z) ** 2) ** 0.5
) ** 0.5 / np.sqrt(2)
w = lambda w0, z: (w0 ** 2 + (c * z / w0) ** 2) ** 0.5
zr = lambda w0: w0 ** 2 / c
fwhm_z = lambda z,w0: w(w0,z)/fwhm_fac
w0_hor = w0(fwhm_hor*fwhm_fac,self.d_kbhor+z_fochor)
w0_ver = w0(fwhm_ver*fwhm_fac,self.d_kbver+z_focver)
fwhm_z = lambda z, w0: w(w0, z) / fwhm_fac
w0_hor = w0(fwhm_hor * fwhm_fac, self.d_kbhor + z_fochor)
w0_ver = w0(fwhm_ver * fwhm_fac, self.d_kbver + z_focver)
print(w0_hor)
res = {}
res['target'] = (fwhm_z(self.d_target+z_fochor,w0_hor),fwhm_z(self.d_target+z_focver,w0_ver))
res['win1'] = (fwhm_z(self.d_win1+z_fochor,w0_hor),fwhm_z(self.d_win1+z_focver,w0_ver))
res['win2'] = (fwhm_z(self.d_win2+z_fochor,w0_hor),fwhm_z(self.d_win2+z_focver,w0_ver))
res['att'] = (fwhm_z(self.d_att+z_fochor,w0_hor),fwhm_z(self.d_att+z_focver,w0_ver))
res['sample'] = (fwhm_z(z_fochor,w0_hor),fwhm_z(z_focver,w0_ver))
res["target"] = (
fwhm_z(self.d_target + z_fochor, w0_hor),
fwhm_z(self.d_target + z_focver, w0_ver),
)
res["win1"] = (
fwhm_z(self.d_win1 + z_fochor, w0_hor),
fwhm_z(self.d_win1 + z_focver, w0_ver),
)
res["win2"] = (
fwhm_z(self.d_win2 + z_fochor, w0_hor),
fwhm_z(self.d_win2 + z_focver, w0_ver),
)
res["att"] = (
fwhm_z(self.d_att + z_fochor, w0_hor),
fwhm_z(self.d_att + z_focver, w0_ver),
)
res["sample"] = (fwhm_z(z_fochor, w0_hor), fwhm_z(z_focver, w0_ver))
# res['fwhm_kbver'] = (fwhm_z(self.d_kbver+z_fochor,w0_hor),fwhm_z(self.d_kbver+z_focver,w0_ver))
# res['fwhm_kbhor'] = (fwhm_z(self.d_kbhor+z_fochor,w0_hor),fwhm_z(self.d_kbhor+z_focver,w0_ver))
return res
def move_hex_for_kb_angles(self,the_kbver,the_kbhor):
pos = self.calc_positions(the_kbver,the_kbhor)
x = pos['x_hex']
y = pos['y_hex']
rx = pos['rx_hex']*180/np.pi
ry = pos['ry_hex']*180/np.pi
z=rz=0.
ax,ay,az,arx,ary,arz = self.usd_table.get_coordinates()
print(f"present upstream large hexapod position is (x/mm,y/mm,z/mm,rx/°,ry/°,rz/°) = ({ax:g},{ay:g},{az:g},{arx:g},{ary:g},{arz:g})")
print(f"moving to (x/mm,y/mm,z/mm,rx/°,ry/°,rz/°) = ({x:g},{y:g},{z:g},{rx:g},{ry:g},{rz:g})")
if not input("start moving upstream large hexapod? (y/n)")=="y":
def move_hex_for_kb_angles(self, the_kbver, the_kbhor):
pos = self.calc_positions(the_kbver, the_kbhor)
x = pos["x_hex"]
y = pos["y_hex"]
rx = pos["rx_hex"] * 180 / np.pi
ry = pos["ry_hex"] * 180 / np.pi
z = rz = 0.0
ax, ay, az, arx, ary, arz = self.usd_table.get_coordinates()
print(
f"present upstream large hexapod position is (x/mm,y/mm,z/mm,rx/°,ry/°,rz/°) = ({ax:g},{ay:g},{az:g},{arx:g},{ary:g},{arz:g})"
)
print(
f"moving to (x/mm,y/mm,z/mm,rx/°,ry/°,rz/°) = ({x:g},{y:g},{z:g},{rx:g},{ry:g},{rz:g})"
)
if not input("start moving upstream large hexapod? (y/n)") == "y":
print("did nothing")
return
else:
self.usd_table.move_to_coordinates(x,y,z,rx,ry,rz)
self.usd_table.move_to_coordinates(x, y, z, rx, ry, rz)
class KBMirrorBernina_new(Assembly):
def __init__(
self,
pvname_hor,
pvname_ver,
usd_table=None,
d_kbver=3350.0,
d_kbhor=2600.0,
d_hex=1600.0,
d_win1=1945.0,
d_win2=1330.0,
d_target=1520.0,
d_att=1420.0,
):
"""All distances are from sample interaction point at straight beam (no kb deflection), the units are expected in mm"""
super().__init__(name=name)
self.kb_ver = kb_ver
self.kb_hor = kb_hor
self.usd_table = usd_table
self.d_kbver = d_kbver
self.d_kbhor = d_kbhor
self.d_hex = d_hex
self.d_att = d_att
self.d_win2 = d_win2
self.d_win1 = d_win1
self.d_target = d_target
self._add(MotorRecord, pvname_hor + ":W_X", name="x_hor")
self._add(MotorRecord, pvname_hor + ":W_Y", name="y_hor")
self._add(MotorRecord, pvname_hor + ":W_RY", name="y_hor")
self._add(MotorRecord, pvname_hor + ":W_RY", name="pitch_hor")
self._add(MotorRecord, pvname_hor + ":W_RZ", name="roll_hor")
self._add(MotorRecord, pvname_hor + ":W_RX", name="yaw_hor")
self._add(MotorRecord, pvname_hor + ":BU", name="bend_upstream_hor")
self._add(MotorRecord, pvname_hor + ":BD", name="bend_downstream_hor")
self._add(MotorRecord, pvname_hor + ":TY1", name="y1_phys_hor")
self._add(MotorRecord, pvname_hor + ":TY2", name="y2_phys_hor")
self._add(MotorRecord, pvname_hor + ":TY3", name="y3_phys_hor")
self._add(MotorRecord, pvname_hor + ":TX1", name="x1_phys_hor")
self._add(MotorRecord, pvname_hor + ":TX2", name="x2_phys_hor")
self._add(
PvRecord,
pvsetname=Id + ":CURV_SP",
pvreadbackname=Id + ":CURV",
accuracy=0.002,
name="curv",
)
addPvRecordToSelf(
self,
pvsetname=Id + ":ASYMMETRY_SP",
pvreadbackname=Id + ":ASYMMETRY",
accuracy=0.002,
name="asym",
)
def calc_positions(self, the_kbver, the_kbhor):
"""angles in rad"""
y_kbhor = np.tan(2 * the_kbver) * np.abs(self.d_kbver - self.d_kbhor)
rx_kbhor = -2 * the_kbver
y_hex = np.tan(2 * the_kbver) * np.abs(self.d_kbver - self.d_hex)
x_hex = np.tan(2 * the_kbhor) * np.abs(self.d_kbhor - self.d_hex)
rx_hex = rx_kbhor
ry_hex = 2 * the_kbhor
return {
"y_kbhor": y_kbhor,
"rx_kbhor": rx_kbhor,
"x_hex": x_hex,
"y_hex": y_hex,
"rx_hex": rx_hex,
"ry_hex": ry_hex,
}
def calc_fwhm(self, fwhm_hor, fwhm_ver, z_focver=0, z_fochor=0, E_phot=None):
""" E_phot in eV, length units in mm."""
lam = constants.c * constants.h / constants.electron_volt / E_phot
print(lam * 1e10)
fwhm_fac = 1 / np.sqrt(2 * np.log(2)) # w = fwhm_fac*fwhm
# div_ver = np.arctan(fwhm_ver*fwhm_fac/2/(self.d_kbver+z_focver)) #half divergence
# div_hor = np.arctan(fwhm_hor*fwhm_fac/2/(self.d_kbhor+z_fochor))
c = lam / np.pi * 1e3
w0 = lambda w, z: (
w ** 2 - (w ** 4 - (2 * c * z) ** 2) ** 0.5
) ** 0.5 / np.sqrt(2)
w = lambda w0, z: (w0 ** 2 + (c * z / w0) ** 2) ** 0.5
zr = lambda w0: w0 ** 2 / c
fwhm_z = lambda z, w0: w(w0, z) / fwhm_fac
w0_hor = w0(fwhm_hor * fwhm_fac, self.d_kbhor + z_fochor)
w0_ver = w0(fwhm_ver * fwhm_fac, self.d_kbver + z_focver)
print(w0_hor)
res = {}
res["target"] = (
fwhm_z(self.d_target + z_fochor, w0_hor),
fwhm_z(self.d_target + z_focver, w0_ver),
)
res["win1"] = (
fwhm_z(self.d_win1 + z_fochor, w0_hor),
fwhm_z(self.d_win1 + z_focver, w0_ver),
)
res["win2"] = (
fwhm_z(self.d_win2 + z_fochor, w0_hor),
fwhm_z(self.d_win2 + z_focver, w0_ver),
)
res["att"] = (
fwhm_z(self.d_att + z_fochor, w0_hor),
fwhm_z(self.d_att + z_focver, w0_ver),
)
res["sample"] = (fwhm_z(z_fochor, w0_hor), fwhm_z(z_focver, w0_ver))
# res['fwhm_kbver'] = (fwhm_z(self.d_kbver+z_fochor,w0_hor),fwhm_z(self.d_kbver+z_focver,w0_ver))
# res['fwhm_kbhor'] = (fwhm_z(self.d_kbhor+z_fochor,w0_hor),fwhm_z(self.d_kbhor+z_focver,w0_ver))
return res
def move_hex_for_kb_angles(self, the_kbver, the_kbhor):
pos = self.calc_positions(the_kbver, the_kbhor)
x = pos["x_hex"]
y = pos["y_hex"]
rx = pos["rx_hex"] * 180 / np.pi
ry = pos["ry_hex"] * 180 / np.pi
z = rz = 0.0
ax, ay, az, arx, ary, arz = self.usd_table.get_coordinates()
print(
f"present upstream large hexapod position is (x/mm,y/mm,z/mm,rx/°,ry/°,rz/°) = ({ax:g},{ay:g},{az:g},{arx:g},{ary:g},{arz:g})"
)
print(
f"moving to (x/mm,y/mm,z/mm,rx/°,ry/°,rz/°) = ({x:g},{y:g},{z:g},{rx:g},{ry:g},{rz:g})"
)
if not input("start moving upstream large hexapod? (y/n)") == "y":
print("did nothing")
return
else:
self.usd_table.move_to_coordinates(x, y, z, rx, ry, rz)