Commit 0e1ae2d1 authored by Yoann Sallaz Damaz's avatar Yoann Sallaz Damaz
Browse files

suite

parent 53efe384
Pipeline #51993 failed with stages
......@@ -6,7 +6,7 @@ from time import sleep
# Following parameters cannot be done remotely
# FREQ: 0 (3.3Mhz)
# QUADR: 1 (quadrature signals used)
# SENS: 0 (counting direction)
# SENS: 0 (counting direction) # mettre a 1 sur FIP2
# POLREF: 0 (reference signal polarity)
# POLIND: 0 (index signal polarity)
# RS: 1 (Addressed RS232 without echo)
......@@ -47,8 +47,8 @@ class bac24(object):
# set the current position and the offset to 0
self.clearpos()
# set the keybord inactive
self.key(0)
# set the keybord inactive 0 active 1
self.key(1)
# set the display decimal
self.send_and_read(b"$ADEC0;\r\n")
......@@ -63,16 +63,23 @@ class bac24(object):
def zero(self):
print("bac24_zero()")
self.send_and_read(b"$APLA1,1,0,0;\r\n")
self.send_and_read(b"$APLA1,1,0,0;\r\n",2)
def ramp(self, start_pos, end_pos):
# Define the start_pos and end_pos for level 1 of output 1
#start_step = start_pos * 12800; # in encoder steps
#end_step = * 12800; # in encoder steps
start_step = -1*end_pos * 12800; # in encoder steps
end_step = -1*start_pos * 12800; # in encoder steps
start_step = start_pos * 12800 # in encoder steps
end_step = end_pos * 12800 # in encoder steps
print("bac24_ramp: start: %d, end: %d"%(start_step, end_step))
self.send_and_read(b"$APLA1,1,%d,%d;\r\n"%(start_step, end_step))
self.send_and_read(b"$APLA1,1,%d,%d;\r\n"%(start_step, end_step),2)
def ramp_cycle(self, start_pos, end_pos, next_periode_pos, bac_out_num=1):
# Define the start_pos and end_pos for level 1 of output 1 in cycle mode
# 0, 0.8, 1 -> open from 0 to 0.8, close from 0.8 to 1, open from 1 to 1.8, etc.
start_step = start_pos * 12800 # in encoder steps
end_step = end_pos * 12800 # in encoder steps
periode = next_periode_pos * 12800
print("bac24_ramp_cycle: start: %d, end: %d, periode: %d"%(start_step, end_step, periode))
self.send_and_read(b"$APLC%d,%d,%d,%d;\r\n"%(bac_out_num, periode, start_step, end_step),3)
def alarm(self):
# Return the ALARM status
......@@ -102,3 +109,5 @@ class bac24(object):
# Read the actual ramp range (where the shutter is open)
return self.send_and_read(b"$ALIT1,1;\r\n")
def status(self):
self.send_and_read(b"$AETAT;\r\n",13)
from bliss.setup_globals import *
import time
def acq_externalSingle(expo_s, step_deg, start_angle_deg, end_angle_deg):
readout = pilatus_6m.proxy.latency_time
velocity = step_deg/(expo_s+readout)
nb_img = int((end_angle_deg-start_angle_deg)/step_deg)
omega.sync_hard()
#bac24.init()
pilatus_6m.proxy.reset()
#pilatus_6m.camera.threshold=energy.position
pilatus_6m.camera.fill_mode = 'ON'
pilatus_6m.acquisition.trigger_mode = "EXTERNAL_TRIGGER"
pilatus_6m.proxy.saving_mode = "AUTO_FRAME"
pilatus_6m.acquisition.nb_frames = nb_img
pilatus_6m.proxy.acq_expo_time = expo_s
pilatus_6m.proxy.saving_overwrite_policy = "OVERWRITE"
pilatus_6m.proxy.saving_directory="/lima_data/pics"
pilatus_6m.proxy.saving_prefix="pilatus_6m_"
pilatus_6m.proxy.saving_suffix=".cbf"
pilatus_6m.proxy.saving_index_format="%04d"
pilatus_6m.proxy.saving_format="CBF"
pilatus_6m.proxy.saving_header_delimiter=["|", ";", ":"]
pilatus_6m.proxy.saving_next_number =0
headers = list()
start_angles = list()
headercommon = {}
headercommon["file_comments"] = ""
headercommon["N_oscillations"] = nb_img
headercommon["Oscillation_axis"] = "omega"
headercommon["Beam_xy"] = "(%.2f, %.2f) pixels" % (pilatus_6m.image.width/2, pilatus_6m.image.height/2)
headercommon["Detector_distance"] = "%f m" % ( detfwd.position / 1000.0)
headercommon["Wavelength"] = "%f A" % energy.controller._tagged["wavelength"][0].position
headercommon["Threshold_setting"] = "%d eV" % pilatus_6m.camera.threshold
headercommon["Count_cutoff"] = "1048500"
headercommon["Tau"] = "= 0 s"
headercommon["Exposure_period"] = "%f s" % (expo_s + readout)
headercommon["Exposure_time"] = "%f s" % expo_s
for i in range(nb_img):
start_angles.append("%0.4f deg." % (start_angle_deg + step_deg * i))
for i, start_angle in enumerate(start_angles):
header = "\nPILATUS 6M, S/N 60-0106, Soleil\n"
header += "# %s\n" % time.strftime("%Y/%b/%d %T")
header += "\nSilicon sensor, thickness 0.000320 m\n"
header += "\nPixel_size 172e-6 m x 172e-6 m\n"
headercommon["Start_angle"] = start_angle
for key, value in headercommon.items():
header += "# %s %s\n" % (key, value)
headers.append("%d : array_data/header_contents|%s;" % (i, header))
pilatus_6m.proxy.setImageHeader(headers)
omega.velocity = 20
umv(omega,start_angle_deg-1)
omega.velocity = velocity
bac24.ramp(start_angle_deg,end_angle_deg)
pilatus_6m.stopAcq()
pilatus_6m.prepareAcq()
pilatus_6m.startAcq()
mvr(omega, end_angle_deg-start_angle_deg+1)
bac24.zero()
omega.velocity=20
umv(omega,0)
def dstop_up():
wcd07f.set("dstop_up",1)
def dstop_down():
wcd07f.set("dstop_up",0)
def bstop1_up():
wcd07f.set("bstop1",1)
def bstop1_down():
wcd07f.set("bstop1",0)
def opensh():
fast_shutter_pseudo.open_manual()
def closesh():
fast_shutter_pseudo.close_manual()
\ No newline at end of file
from bliss.config import static as static_config
from bliss.comm.modbus import ModbusTcp
from bliss.config.channels import Cache, Channel
import gevent
import time
#<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
#<TOPICSLIST>
......@@ -60,18 +61,72 @@ def float_to_word(val):
def word_to_float(val):
return (val-32767)/100.
class SampleChangerState:
"""
Enumeration of sample changer states
"""
Unknown = 0
Ready = 1
Loaded = 2
Loading = 3
Unloading = 4
Selecting = 5
Scanning = 6
Resetting = 7
Charging = 8
Moving = 9
ChangingMode = 10
StandBy = 11
Disabled = 12
Alarm = 13
Fault = 14
Initializing = 15
Closing = 16
STATE_DESC = {
Ready: "Ready",
Loaded: "Loaded",
Alarm: "Alarm",
Charging: "Charging",
Disabled: "Disabled",
Fault: "Fault",
Loading: "Loading",
Resetting: "Resetting",
Scanning: "Scanning",
Selecting: "Selecting",
Unloading: "Unloading",
Moving: "Moving",
ChangingMode: "Changing Mode",
StandBy: "StandBy",
Initializing: "Initializing",
Closing: "Closing",
}
@staticmethod
def tostring(state):
return SampleChangerState.STATE_DESC.get(state, "Unknown")
class grob_FIP(object):
GONIO_SAMPLE_COLLECT_STATE = 1
GONIO_SAMPLE_MOUNT_STATE = 2
def __init__(self, name, config, config_objects=None):
self._config_objects = config_objects
ip = config.get("ip")
port = config.get("port")
self.client = ModbusTcp(ip, port=int(port))
self.SIMU = config.get("SIMULATION")
self.command = { "stop":1, "home":2, "mount_sample":3, "dismount_sample":4,
"mount_plate":5, "dismount_plate":6, "mount_gonio":7, "dismount_gonio":8,
"send_setup":9, "wash":10, "anneal":11, "mount_versa_pin":12,
"move_rel":13, "move_abs":14, "expose":15, "open_grip":16,
"close_grip":17, "set_grip":18, "set_angles":19 }
"close_grip":17, "set_grip":18, "set_angles":19, "force_mounted_sample":22 }
self.addr = { "Command": {"addr":0, "struct_format":"16H"},
"Status": {"addr":16, "struct_format":"H"},
"CurMode": {"addr":17, "struct_format":"H"},
......@@ -114,6 +169,9 @@ class grob_FIP(object):
15:"Exposing", 16:"Plate in position",
17:"1D in position", 18:"Versapin in position", 0:"Unknown" }
self.state_grob=1
self.state_gonio=1
self.Status=None
self.CurrentMode=None
self.GrobIsInit=None
......@@ -145,6 +203,35 @@ class grob_FIP(object):
self.ErrorMsg=None
self.currentPuckType=None
#real device
self.omega = config["gonio_omega"]
self.xomega = config["gonio_xomega"]
self.zomega = config["gonio_zomega"]
self.x = config["gonio_x"]
self.y = config["gonio_y"]
self.z = config["gonio_z"]
self.kappa = config["gonio_kappa"]
self.detfw = config["det_move"]
#geometry
#mount sample
self.omega_mountsample = config["omega_mountsample"]
self.kappa_mountsample = config["kappa_mountsample"]
self.x_mountsample = config["x_mountsample"]
self.y_mountsample = config["y_mountsample"]
self.z_mountsample = config["z_mountsample"]
self.xomega_mountsample = config["xomega_mountsample"]
self.zomega_mountsample = config["zomega_mountsample"]
#collect sample
self.omega_collectsample = config["omega_collectsample"]
self.kappa_collectsample = config["kappa_collectsample"]
self.x_collectsample = config["x_collectsample"]
self.y_collectsample = config["y_collectsample"]
self.z_collectsample = config["z_collectsample"]
self.xomega_collectsample = config["xomega_collectsample"]
self.zomega_collectsample = config["zomega_collectsample"]
#READ - Robot Memory
self.read_all_memory()
......@@ -156,7 +243,79 @@ class grob_FIP(object):
param.insert(0,self.command.get(cmd))
print(param)
self.client.write_registers(cominfo.get("addr"), cominfo.get("struct_format"), param)
def _move_gonio(self, motor_list_first, target_list_first,
motor_list_next, target_list_next,
checkonly=False):
for motor_list, target_list in ((motor_list_first,target_list_first),
(motor_list_next,target_list_next)):
if not checkonly:
for mot,target in list(zip(motor_list,target_list)):
mot.move(target,wait=False)
notok=True
with gevent.Timeout(15,False):
while notok:
allok=True
for mot,target in list(zip(motor_list,target_list)):
if mot.is_moving or abs(mot.position-target)>0.1:
allok=False
notok=not(allok)
if checkonly:
break
time.sleep(1)
if notok :
return False
return True
def move_gonio_in_sample_mount_geo(self, checkonly=False):
motor_list_first = [ self.omega, self.y]
target_list_first = [ self.omega_mountsample, self.y_mountsample]
motor_list_next = [ self.kappa,
self.x,
self.z,
self.xomega,
self.zomega]
target_list_next = [self.kappa_mountsample,
self.x_mountsample,
self.z_mountsample,
self.xomega_mountsample,
self.zomega_mountsample]
#first y and omega to be sure no collision
if self.SIMU:
return self.state_gonio == 2
else:
return self._move_gonio(motor_list_first,target_list_first,
motor_list_next,target_list_next,
checkonly)
def move_gonio_in_sample_collect_geo(self, checkonly=False):
motor_list_first = [ self.kappa,
self.x,
self.z,
self.xomega,
self.zomega]
target_list_first = [self.kappa_collectsample,
self.x_collectsample,
self.z_collectsample,
self.xomega_collectsample,
self.zomega_collectsample]
motor_list_next = [ self.omega, self.y]
target_list_next = [ self.omega_collectsample, self.y_collectsample]
#and by y and omega to be sure no collision
if self.SIMU :
return self.state_gonio == 1
else:
return self._move_gonio(motor_list_first,target_list_first,
motor_list_next,target_list_next,
checkonly)
def check_gonio_in_sample_mount_geo(self):
return self.move_gonio_in_sample_mount_geo(checkonly=True)
def stop(self):
self.send_command("stop")
......@@ -164,10 +323,43 @@ class grob_FIP(object):
self.send_command("home")
def mount_sample(self, sample_number):
self.send_command("mount_sample", [sample_number])
if self.SIMU:
self.state_grob = 1
#gonio position to mount
if self.SIMU:
self.state_gonio = 2
time.sleep(1)
if not self.move_gonio_in_sample_mount_geo():
return False
#robot mount
if self.SIMU:
self.state_grob = 2
self.send_command("force_mounted_sample", [sample_number])
else:
self.send_command("mount_sample", [sample_number])
with gevent.Timeout(15,False):
while self.NumSampleMounted != sample_number:
self.read_all_memory()
print(self.NumSampleMounted)
time.sleep(1)
if self.NumSampleMounted != sample_number:
return False
if self.SIMU:
self.state_grob = 1
time.sleep(1)
self.state_gonio = 1
#gonio position for collecting sample
if not self.move_gonio_in_sample_collect_geo():
return False
def dismount_sample(self):
self.send_command("dismount_sample")
#self.send_command("dismount_sample")
self.send_command("force_mounted_sample", [0])
def mount_plate(self, sample_number):
self.send_command("mount_plate", [sample_number])
......@@ -262,6 +454,11 @@ class grob_FIP(object):
self.CurPosZ = data[27]
self.ErrorMsg = data[28]
self.currentPuckType = data[29]
try:
if self.mounted_sample_chan.value != self.NumSampleMounted:
self.mounted_sample_chan.value = self.NumSampleMounted
except:
pass
def print_setup(self):
self.read_all_memory()
......@@ -288,12 +485,38 @@ class grob_FIP(object):
def set_grip(self, grip_type):
self.send_command("set_grip", [grip_type])
def get_status(self):
def get_state(self):
self.read_all_memory()
print(self.status_code.get(self.Status))
return self.Status
if self.SIMU:
state = self.state_grob
else:
state = self.Status
if state ==1 and self.NumSampleMounted>0:
value = SampleChangerState.Loaded
elif state == 1:
value = SampleChangerState.Ready
elif state == 2:
value = SampleChangerState.Loading
try:
if self.transfer_state_chan.value != value:
self.transfer_state_chan.value =value
except:
pass
return value
def gonio_state(self):
if self.move_gonio_in_sample_collect_geo(checkonly=True):
return self.GONIO_SAMPLE_COLLECT_STATE
elif self.move_gonio_in_sample_mount_geo(checkonly=True):
return self.GONIO_SAMPLE_MOUNT_STATE
else:
0
def get_position():
def get_status(self):
self.read_all_memory()
return self.status_code.get(self.Status)
def get_position(self):
self.read_all_memory()
return (self.CurPosX, self.CurPosY, self.CurPosZ)
......@@ -345,5 +568,10 @@ class grob_FIP(object):
def callback_samples_map(self, fct):
self.samples_map_chan = Channel("samples_map", default_value=dict(zip(range(30), ["unknown"] * 30)), callback=fct)
def mount_dismount_is_in_progress(self):
state_grob = self.get_state()
state_gonio = self.gonio_state()
return state_grob==SampleChangerState.Loading or state_gonio != self.GONIO_SAMPLE_COLLECT_STATE
\ No newline at end of file
......@@ -19,6 +19,7 @@ import termplotlib as tpl
import urllib.request
import scipy.optimize as opt
import matplotlib.pyplot as plt
from scipy import ndimage
def gauss(x, p): # p[0]==mean, p[1]==stdev
......@@ -29,18 +30,12 @@ def analyseImg():
name="/tmp/pictures/test.jpg"
X = np.arange(0,800,1)
img = Image.open(name, "r")
imgcrp = img.crop((620, 0, 660, 800))
pix = np.asarray(img)
projection = np.sum(np.sum(imgcrp, axis = 1), axis=1)
imgcrp = img.crop((700, 0, 1100, 800))
pix = np.asarray(imgcrp)
pix2 = np.where(pix>50,pix,0)
projection = np.sum(np.sum(pix2, axis = 1), axis=1)
projection = np.true_divide(projection, np.sum(projection))
# Fit a gaussian
p0 = [0,1] # Inital guess is a normal distribution
errfunc = lambda p, x, y: gauss(x, p) - y # Distance to the target function
p1, success = opt.leastsq(errfunc, p0[:], args=(X, projection))
if success :
return p1[0]
else:
return -1
return ndimage.center_of_mass(projection)[0]
......@@ -405,9 +400,28 @@ def scanMovehM1(relMin, relMax, step):
def mesure_bend_M2(Min, Max, nbPoint):
saveMonitorsImage("0001","ref")
m2upPos=[]
position=[]
for pos in np.linspace(Min, Max, nbPoint):
m2up.move(pos, wait=True)
saveMonitorsImage("0001","m2up_%f"%pos)
value=0
nbpoint=0
for i in range(0,10):
saveMonitorsImage("0001","m2up_%f"%pos)
urllib.request.urlretrieve("http://bm07recorder.esrf.fr:7006/jpg/image.jpg", "/tmp/pictures/test.jpg")
resu = analyseImg()
if resu != -1:
print(resu)
value+=resu
nbpoint+=1
time.sleep(0.3)
if nbpoint!=0:
resu = value/float(nbpoint)
print(pos, resu)
m2upPos.append(pos)
position.append(resu)
print(m2upPos)
print(position)
def mesure_bend_M2_sans_M2(Min, Max, nbPoint):
......@@ -419,7 +433,7 @@ def mesure_bend_M2_sans_M2(Min, Max, nbPoint):
#fastscan.gamma2_short.scan()
value=0
nbpoint=0
for i in range(0,10):
for i in range(0,5):
saveMonitorsImage("0001","utz_%f"%pos)
urllib.request.urlretrieve("http://bm07recorder.esrf.fr:7006/jpg/image.jpg", "/tmp/pictures/test.jpg")
resu = analyseImg()
......@@ -485,7 +499,7 @@ def saveMonitorsImage(cam,string): #cam in binary string 0000 to 1111, each char
urllib.request.urlretrieve("http://bm07recorder.esrf.fr:7009/jpg/image.jpg", path + now + "_fluo2_" + string + ".jpg")
if cam[3:4] == "1": # download fluo3 camera picture
urllib.request.urlretrieve("http://bm07recorder.esrf.fr:7006/jpg/image.jpg", path + now + "_fluo3_" + string + ".jpg")
sleep(1)
sleep(0.5)
def scanMovehM1Sl0(relMin, relMax, step, pics=False, sourceAngle_uRad=0):
......@@ -594,4 +608,19 @@ def md2_wakeup():
for mot in motlist:
mot.move(mot.position+sign*0.1, wait=False)
while any(mot.is_moving for mot in motlist):
sleep(0.1)
\ No newline at end of file
sleep(0.1)
def flux_from_diode_val(diode_mA, NRJ_keV = 12.65, Si_um = 300, Air_cm = 6, Al_um = 30):
Si_density = 2.35 #g/cm3
Air_density = 1.23E-3 #g/cm3
Al_density = 2.7 #g/cm3
CoefSI = 1.6E-19*NRJ_keV*1000*(1-exp(-exp(0.0133*(log(NRJ_keV))**3-0.1934*(log(NRJ_keV))**2-2.2757*(log(NRJ_keV))+9.6049)*Si_um*0.0001*Si_density))
CoefAir = exp(-exp(0.009*(log(NRJ_keV))**3-0.1332*(log(NRJ_keV))**2-2.6392*(log(NRJ_keV))+8.2371)*Air_cm*Air_density)
CoefAl = exp(-exp(0.1376*(log(NRJ_keV))**3-1.2533*(log(NRJ_keV))**2-2.2957*(log(NRJ_keV))-0.9172)*Al_um*0.0001*Al_density)
flux = 3.62*diode_mA*0.001/CoefSI/CoefAir/CoefAl
print("%e ph.s"%flux)
return "{:e}".format(flux)
......@@ -5,34 +5,53 @@ from bliss.common.utils import object_method
from bliss.common import *
import math
from bliss.config.static import get_config
from bliss import global_map
class pseudo_gonio(CalcController):
def __init__(self, *args, **kwargs):
CalcController.__init__(self, *args, **kwargs)
self.omega = None
self.x = None
self.z = None
self.omega = None
self._pos_dict = {}
def initialize_axis(self, axis):
CalcController.initialize_axis(self, axis)
self.omega = self._tagged.get("omega", [None])[0]
self.x = self._tagged.get("x", [None])[0]
self.z = self._tagged.get("z", [None])[0]
self.omega = self._tagged.get("omega", [None])[0]
axis.no_offset = True
def calc_from_real(self, positions_dict):
calc_dict = dict()
omegarad = math.radians(positions_dict["omega"])
verticalpos = positions_dict["x"] * math.sin(-omegarad) + positions_dict["z"] * math.cos(-omegarad)
calc_dict.update({"sample_vertical": (verticalpos)})
return calc_dict
def calc_to_real(self, positions_dict):
real_dict = dict()
omegarad = math.radians(positions_dict["omega"])
vert = positions_dict["sample_vertical"]
hor = sampx * math.cos(omegarad) + sampy * math.sin(omegarad)
x = vert * math.sin(-omegarad) + hor * math.cos(-omegarad)