Commit d52d12e3 authored by Sauerwein Nick Jacob's avatar Sauerwein Nick Jacob
Browse files

spectometer fist tested, bugg in restart solved

parent 8ecef216
......@@ -9,13 +9,13 @@ import numpy as np
import matplotlib.pyplot as plt
theta0 = 0./180 * np.pi
R0 = 1.06
R0 = 1.0
theta1 = 40./180 * np.pi
R1 = 0.94
R1 = 1.0
theta2 = 80./180 * np.pi
R2 = 0.81
R2 = 1.0
z0 = R0 * np.exp(1j * theta0)
z1 = R1 * np.exp(1j * theta1)
......@@ -41,11 +41,4 @@ e = fit_circle(z.real, z.imag)
def cor(R):
theta= R*2*np.pi/360.
return np.round((np.cos(theta)*e[0]-np.sin(theta)*e[1]),6)
#th=R0-np.linspace(0, 360, 100)
#plt.figure("correction factor")
#plt.plot(th, cor(th))
#plt.xlabel("R [deg]")
#plt.ylabel("corr [mm]")
#plt.show()
\ No newline at end of file
......@@ -10,12 +10,9 @@ import numpy as np
import time
import sys
sys.path.append('directory where spectroanalyser scripts are')
import sys
sys.path.insert(0, '../../scripts/')
sys.path.insert(0, '../Nick/spectroanalyser/scripts/')
import sympy as sym
import numpy as np
......@@ -37,16 +34,16 @@ lattice_elements: string of connected lattice elements (i.e. Q1Q2Q3D1). Th
because at the experiment we will only place them in the normal order Q1Q2Q3D1
Q1_gradient: gradient of Q1 magnet [T/m]
Q1_angle: angle of b_2 in complex plane (two times the real rotation in the laboratory frame of reference)
Q1_angle: angle [deg] of b_2 in complex plane (two times the real rotation in the laboratory frame of reference)
Q2_gradient: gradient of Q2 magnet [T/m]
Q2_angle: angle of b_2 in complex plane (two times the real rotation in the laboratory frame of reference)
Q2_angle: angle [deg] of b_2 in complex plane (two times the real rotation in the laboratory frame of reference)
Q3_gradient: gradient of Q3 magnet [T/m]
Q3_angle: angle of b_2 in complex plane (two times the real rotation in the laboratory frame of reference)
Q3_angle: angle [deg] of b_2 in complex plane (two times the real rotation in the laboratory frame of reference)
D1_field: field of D1 magnet [mT]
D1_angle: angle of b_1 in complex plane (the real rotation in the laboratory frame of reference)
D1_angle: angle [deg] of b_1 in complex plane (the real rotation in the laboratory frame of reference)
d_source_Q1: distance between jet and Q1
d_Q1_Q2: distance between Q1 and Q2
......@@ -54,7 +51,7 @@ d_Q2_Q3: distance between Q2 and Q3
d_Q3_D1: distance between Q3 and D1
d_D1_screen: distance between D1 and screen
E0: reference energy. The energy that will be used to set up the focusing and deflection conditions
E0: reference energy [MeV]. The energy that will be used to set up the focusing and deflection conditions
deflection: distance that particles at reference energy are shifted on screen due to dipole (the dipole will be set when special function spec_set_dispersion is started)
delfection_angle: [deg] direction in which the electrons should be dispersed
......@@ -62,10 +59,23 @@ delfection_angle: [deg] direction in which the electrons should be dispers
measurement n.a
'''
default_config = {'max_angle': -22.9,
'attenuation': 100,
'comp_lin': 38.020,
'channel': 1}
default_config = {'lattice_elements': 'Q1Q2Q3D1',
'Q1_gradient': 0.,
'Q1_angle': 0.,
'Q2_gradient': 0.,
'Q2_angle': 0.,
'Q3_gradient': 0.,
'Q3_angle': 0.,
'D1_field': 0.,
'D1_angle': 0.,
'd_source_Q1': 0.15,
'd_Q1_Q2': 0.15,
'd_Q2_Q3': 0.15,
'd_Q3_D1': 0.15,
'd_D1_screen': 0.15,
'E0': 1.,
'deflection': 0.001,
'deflection_angle':0.}
L_Q1 = 0.08
......@@ -78,15 +88,15 @@ L_D1 = 0.08
class SpectroMeter:
def __init__(self, config):
self.halbacharrays = {}
self.config = config
self.halbacharrays = {}
self.config = config
@property
def config(self):
config['lattice_elements'] = ''.join([key for key in halbacharrays.keys()])
config = {}
config['lattice_elements'] = ''.join([key for key in self.halbacharrays.keys()])
config['deflection'] = self.deflection
config['deflection_angle'] = self.deflection_angle
......@@ -142,6 +152,7 @@ class SpectroMeter:
config['d_D1_screen'] = self.d_D1_screen
config['E0'] = self.E0
return config
@config.setter
def config(self, config):
......@@ -151,26 +162,33 @@ class SpectroMeter:
# connect arrays
for i in range(len(lattice_elements)/2):
name = lattice_elements[i:i+2]
for i in range(int(len(lattice_elements)/2)):
name = lattice_elements[2*i:2*i+2]
if name not in self.halbacharrays:
self.halbacharrays[name] = HalbachArray(name)
self.halbacharrays[name] = HalbachArray()
self.halbacharrays[name].connect_motors(name)
if 'Q1' in self.halbacharrays:
Q1 = self.halbacharrays['Q1']
Q1.field = config['Q1_gradient'] * np.exp(1j*config['Q1_angle'])
Q1.field = config['Q1_gradient'] * np.exp(1j*config['Q1_angle']/180*np.pi)
if 'Q2' in self.halbacharrays:
Q2 = self.halbacharrays['Q2']
Q2.field = config['Q2_gradient'] * np.exp(1j*config['Q2_angle'])
Q2.field = config['Q2_gradient'] * np.exp(1j*config['Q2_angle']/180*np.pi)
if 'Q3' in self.halbacharrays:
Q3 = self.halbacharrays['Q3']
Q3.field = config['Q3_gradient'] * np.exp(1j*config['Q3_angle'])
Q3.field = config['Q3_gradient'] * np.exp(1j*config['Q3_angle']/180*np.pi)
if 'D1' in self.halbacharrays:
D1 = self.halbacharrays['D1']
D1.field = config['D1_field'] * np.exp(1j*config['D1_angle'])
D1.field = config['D1_field'] * np.exp(1j*config['D1_angle']/180*np.pi)
self.d_source_Q1= config['d_source_Q1']
self.d_Q1_Q2= config['d_Q1_Q2']
self.d_Q2_Q3= config['d_Q2_Q3']
self.d_Q3_D1= config['d_Q3_D1']
self.d_D1_screen= config['d_D1_screen']
self.E0 = config['E0']
......@@ -183,7 +201,7 @@ class SpectroMeter:
L_qu = np.array([L_Q1, L_Q2, L_Q3])
g1, g2, g3 = sym.symbols('g1 g2')
g1, g2 = sym.symbols('g1 g2')
parameters = [g1, g2]
......@@ -204,20 +222,20 @@ class SpectroMeter:
print ('ATTENTION')
print ('g1 = '+str(config[0]))
print ('g1 not in ['+str(self.halbacharrays['Q1'].max_field)+', '+str(self.halbacharrays['Q1'].max_field)+']')
print ('g1 not in ['+str(self.halbacharrays['Q1'].min_field)+', '+str(self.halbacharrays['Q1'].max_field)+']')
if np.abs(config[1]) > self.halbacharrays['Q2'].max_field or np.abs(config[1]) < self.halbacharrays['Q2'].min_field:
print ('ATTENTION')
print ('g2 = '+str(config[1]))
print ('g2 not in ['+str(self.halbacharrays['Q2'].max_field)+', '+str(self.halbacharrays['Q2'].max_field)+']')
print ('g2 not in ['+str(self.halbacharrays['Q2'].min_field)+', '+str(self.halbacharrays['Q2'].max_field)+']')
if np.abs(config[0]) > self.halbacharrays['Q3'].max_field or np.abs(config[1]) < self.halbacharrays['Q3'].min_field:
print ('ATTENTION')
print ('g1 = '+str(config[0]))
print ('g1 not in ['+str(self.halbacharrays['Q3'].max_field)+', '+str(self.halbacharrays['Q3'].max_field)+']')
print ('g1 not in ['+str(self.halbacharrays['Q3'].min_field)+', '+str(self.halbacharrays['Q3'].max_field)+']')
self.halbacharrays['Q1'].field = config[0]
......@@ -231,50 +249,31 @@ class SpectroMeter:
R = COE.Rf(self.E0, B)
h1 = R * (1 - np.sqrt(1 - (L_D1/R)**2))
h2 = L_D1 * self.d_D1_source / R / np.sqrt(1 - (L_D1/R)**2)
h2 = L_D1 * self.d_D1_screen / R / np.sqrt(1 - (L_D1/R)**2)
return self.deflection - h1 - h2
return (self.deflection - h1 - h2)**2
from scipy.optimize import minimize_scalar
B = minimize_scalar(to_min ).x
B = minimize_scalar(to_min , bounds = [0.000001,COE.Bf(self.E0, L_D1)], method = 'Bounded').x
if np.abs(B) > self.halbacharrays['D1'].max_field or np.abs(B) < self.halbacharrays['D1'].min_field:
print ('ATTENTION')
print ('B = '+str(B))
print ('B not in ['+str(self.halbacharrays['D1'].max_field)+', '+str(self.halbacharrays['D1'].max_field)+']')
print ('B not in ['+str(self.halbacharrays['D1'].min_field)+', '+str(self.halbacharrays['D1'].max_field)+']')
self.halbacharrays['D1'].field = B * np.exp(1j*self.deflection_angle/180*np.pi)
def spec_calibrate(self):
#thing to do:
# Today
# finish stigmatic focus setter
# check bounds ('throw error if focus cannot be reached with current setup')
# scale the coefitiens for the rotating coil
# Tomorrow
# spectrometer
# test code of triplet on 'dry dock'
# install TMCL on lwfaserver
# bring this file into devices
# accelerator
# check result of driving of compressor
# do scans using fc (x, y, z, pressure, pulse length (don't use compressor)) and set up screen
# measure radiation during acceleration
# meet with benedikt and discuss interferometer
# write email to him
for name, array in self.halbacharrays.items():
array.calibrate()
# General
# continue writeup (chapter of classification of lattice elements has to finished)
# find software to organize work (notes and calender in one, how can one access this with all devices ond over the internet?)
def spec_home(self):
for name, array in self.halbacharrays.items():
array.home()
@Pyro4.expose
......@@ -285,7 +284,7 @@ class HalbachArray:
def connect_motors(self, name):
coefs_dphi = np.load('../rotating_coil/'+name+'_coef_phi.npy', encoding = 'latin1').item()
coefs_dphi = np.load('../Nick/rotating_coil/'+name+'_coef_phi.npy', encoding = 'latin1').item()
self.name = name
self.id = int(name[1]) + {'Q': 0, 'D': 3}[name[0]]
self.mag_type = {'D':0, 'Q':1}[name[0]] #mag_type: 0=dipole, 1=quarupole
......@@ -297,15 +296,30 @@ class HalbachArray:
self.inner = HalbachAxis()
self.outer = HalbachAxis()
self.outer.connect(2*num-1, 'l')
self.inner.connect(2*num, 'r')
self.outer.connect(2*self.id-1, 'l')
self.inner.connect(2*self.id, 'r')
self.set_field_parameters()
def set_field_parameters(self):
self.max_field = np.max(np.abs(self.coefs[:,self.mag_type]))
self.min_field = np.min(np.abs(self.coefs[:,self.mag_type]))
if self.name == 'Q1':
self.rotating_coil_calibration = 6.36392067406e-05 / L_Q1 #[T/m/U]
if self.name == 'Q2':
self.rotating_coil_calibration = 5.77530976052e-05 / L_Q2 #[T/m/U]
if self.name == 'Q3':
self.rotating_coil_calibration = (6.36392067406e-05 + 5.77530976052e-05) / 2 / L_Q3 #[T/m/U]
if self.name == 'D1':
self.rotating_coil_calibration = 9.35305665612e-06 #[T/U]
self.max_field = np.max(np.abs(self.coefs[:,self.mag_type])) * self.rotating_coil_calibration
self.min_field = np.min(np.abs(self.coefs[:,self.mag_type])) * self.rotating_coil_calibration
from scipy.interpolate import interp1d
self.coefs_dphi_f = interp1d(self.dphis, np.hstack([self.coefs.T[:,1:],np.array([self.coefs.T[:,1]]).T]))
......@@ -337,7 +351,7 @@ class HalbachArray:
dphi = phio - phii
return self.coefs_dphi_f_per(dphi_wanted)[self.mag_type] * np.exp(1j * phii)
return self.coefs_dphi_f_per(dphi)[self.mag_type] * np.exp(1j * phii) * self.rotating_coil_calibration
@field.setter
......@@ -375,7 +389,7 @@ class HalbachAxis:
def connect(self, mid, orientation, port = "/dev/tty.usbserial-A104PCH7", steps_per_turn = None):
def connect(self, mid, orientation, port = "/dev/ttyUSB1", steps_per_turn = None):
self.serial_port = Serial(port, timeout=2)
self.bus = TMCL.connect(self.serial_port)
......@@ -516,11 +530,11 @@ class HalbachAxis:
return self.motor.axis.get(3)
daemon = Pyro4.Daemon(host = "localhost", port = 9091) # make a Pyro daemon
ns = Pyro4.locateNS() # find the name server
uri = daemon.register(HalbachAxis) # register the greeting maker as a Pyro object
ns.register("HalbachAxis", uri) # register the object with a name in the name server
#daemon = Pyro4.Daemon(host = "localhost", port = 9091) # make a Pyro daemon
#ns = Pyro4.locateNS() # find the name server
#uri = daemon.register(HalbachAxis) # register the greeting maker as a Pyro object
#ns.register("HalbachAxis", uri) # register the object with a name in the name server
print("Ready.")
daemon.requestLoop()
#print("Ready.")
#daemon.requestLoop()
This diff is collapsed.
......@@ -125,10 +125,16 @@ class DevicePool:
for device_name, device in self.devices.items():
device.config = state['config'][device_name]
for device_name, device in self.devices.items():
print (device_name, state['connected'])
if device_name in state['connected']:
self.connect(device_name)
devices_to_connect = state['connected']
while len(devices_to_connect) > 0:
print (devices_to_connect)
device_name = devices_to_connect.pop()
device = self[device_name]
connection_success = self.connect(device_name, savestate = False)
if not connection_success:
devices_to_connect = [device_name]+ devices_to_connect
continue
if device_name in state['to_measure']:
device.make_measurement = True
if device_name in state['to_plot']:
......@@ -164,21 +170,26 @@ class DevicePool:
for name, mod in self.device_modules.items():
self[name] = Device(name, mod)
def connect(self, device_name):
def connect(self, device_name, savestate = True):
obj = getattr(self[device_name].module, self[device_name].name)
needed_devices = np.array(inspect.getargspec(obj.__init__)[0])[2:]
print (self[device_name].name, needed_devices,obj.__init__.__code__.co_varnames)
print ('device: ',self[device_name].name, ' needed devices: ',needed_devices)
for needed_device in needed_devices:
assert (self[needed_device].connected)
if not self[needed_device].connected:
print (needed_device,' not yet all connected')
return False
self[device_name].obj = obj(self[device_name].config_temp, *[self[dev].obj for dev in needed_devices])
self[device_name].connected = True
self.savestate()
if savestate:
self.savestate()
return True
def __getitem__(self, device_name):
return self.devices[device_name]
......@@ -222,6 +233,7 @@ class DevicePool:
def config(self, config):
for device_name, device in self.devices.items():
device.config = config[device_name]
self.savestate()
......
......@@ -29,11 +29,11 @@ class ConfigItemChanger:
self.widget =self.cb
elif type(self.value) == str:
self.text = widgets.Text(value = self.value, describtion = key)
self.text = widgets.Text(value = self.value, description = key)
self.text.on_submit(self.change_str)
self.widget = self.text
elif np.dtype(type(self.value)) == np.dtype('float64'):
self.flt = widgets.Text(value=str(np.round(self.value,4)),description=key, layout = layout_text)
self.flt = widgets.Text(value=str(self.value),description=key, layout = layout_text)
self.step = widgets.FloatText(value=0.1,description='step', layout = layout_text, style = {'description_width': 'initial'})
self.bp = widgets.Button(description='+', layout = layout_bt )
self.bm = widgets.Button(description='-', layout = layout_bt)
......@@ -45,7 +45,7 @@ class ConfigItemChanger:
self.widget = widgets.HBox([self.flt, self.step, self.bm, self.bp])
elif np.dtype(type(self.value)) == np.dtype('int64') or np.dtype(type(self.value)) == np.dtype('int32'):
self.flt = widgets.Text(value=str(np.round(self.value,4)),description=key, layout = layout_text)
self.flt = widgets.Text(value=str(self.value),description=key, layout = layout_text)
self.bp = widgets.Button(description='+1', layout = layout_bt)
self.bm = widgets.Button(description='-1', layout = layout_bt)
......@@ -193,13 +193,13 @@ class DeviceInterface:
def connect_device(self, bt = None):
self.device_pool.connect(self.device_name)
self.bt_connect.button_style = 'success'
self.bt_connect.disabled = True
if self.device_pool.connect(self.device_name):
self.bt_connect.button_style = 'success'
self.bt_connect.disabled = True
def refresh(self):
self.subwidgets = [widgets.HTML('<b> Configuration: </b>')]
self.subwidgets += [ConfigItemChanger(key, self.device).widget for key in collections.OrderedDict(sorted(self.device.config.items())).keys()]
self.subwidgets += [ConfigItemChanger(key, self.device, self.device_pool).widget for key in collections.OrderedDict(sorted(self.device.config.items())).keys()]
self.config_setter.children = self.subwidgets
def measure_device(self, bt = None):
......@@ -207,11 +207,12 @@ class DeviceInterface:
self.device.make_measurement = self.bt_make_measurement.value
self.bt_make_measurement.button_style = self.switch_style[self.bt_make_measurement.value]
self.device.make_plot = self.bt_make_plot.value & self.bt_make_measurement.value
self.bt_make_plot.value = self.bt_make_plot.value & self.bt_make_measurement.value
self.bt_make_plot.button_style = self.switch_style[self.bt_make_plot.value & self.bt_make_measurement.value]
self.bt_make_plot.disabled = not self.bt_make_measurement.value
if self.device.plotable:
self.device.make_plot = self.bt_make_plot.value & self.bt_make_measurement.value
self.bt_make_plot.value = self.bt_make_plot.value & self.bt_make_measurement.value
self.bt_make_plot.button_style = self.switch_style[self.bt_make_plot.value & self.bt_make_measurement.value]
self.bt_make_plot.disabled = not self.bt_make_measurement.value
def plot_device(self, bt = None):
self.device.make_plot = self.bt_make_plot.value
......
No preview for this file type
No preview for this file type
......@@ -8,7 +8,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "52294bd2fe094936b3d2f0b1f2e9d5e6"
"model_id": "c8628717c2e840568147ea4df98e383d"
}
},
"metadata": {},
......
FocusCamera ['BladePositioning', 'DRS4', 'test_device1']
test_device2 ['BladePositioning', 'DRS4', 'test_device1']
test_device1 ['BladePositioning', 'DRS4', 'test_device1']
test_device1 [] ('self', 'config')
FocusCamera config time: 1.1920928955078125e-06
test_device2 config time: 9.5367431640625e-07
test_device1 config time: 1.9073486328125e-06
DRS4 config time: 4.76837158203125e-07
PlasmaCamHorizontal config time: 4.76837158203125e-07
ScreenCamera config time: 4.76837158203125e-07
FaradayCup config time: 4.76837158203125e-07
BladePositioning config time: 1.1920928955078125e-06
Periscope config time: 4.76837158203125e-07
Interferometer config time: 4.76837158203125e-07
ParabolicMirror config time: 4.76837158203125e-07
DelayGenerator config time: 4.76837158203125e-07
Laser config time: 4.76837158203125e-07
DRS4 ['BladePositioning', 'DRS4', 'test_device1']
DRS4 [] ('self', 'config')
FocusCamera config time: 7.62939453125e-06
test_device2 config time: 4.76837158203125e-06
test_device1 config time: 1.239776611328125e-05
DRS4 config time: 0.001991748809814453
PlasmaCamHorizontal config time: 2.384185791015625e-06
ScreenCamera config time: 1.1920928955078125e-06
FaradayCup config time: 1.1920928955078125e-06
BladePositioning config time: 5.0067901611328125e-06
Periscope config time: 1.1920928955078125e-06
Interferometer config time: 1.1920928955078125e-06
ParabolicMirror config time: 9.5367431640625e-07
DelayGenerator config time: 9.5367431640625e-07
Laser config time: 9.5367431640625e-07
PlasmaCamHorizontal ['BladePositioning', 'DRS4', 'test_device1']
ScreenCamera ['BladePositioning', 'DRS4', 'test_device1']
FaradayCup ['BladePositioning', 'DRS4', 'test_device1']
BladePositioning ['BladePositioning', 'DRS4', 'test_device1']
BladePositioning [] ('self', 'config')
rot. stage got stuck... continue
lin. stage got stuck... continue
cor: 0.187542
FocusCamera config time: 4.291534423828125e-06
test_device2 config time: 3.5762786865234375e-06
test_device1 config time: 7.152557373046875e-06
DRS4 config time: 0.0017108917236328125
PlasmaCamHorizontal config time: 3.0994415283203125e-06
ScreenCamera config time: 1.9073486328125e-06
FaradayCup config time: 1.430511474609375e-06
BladePositioning config time: 0.3030738830566406
Periscope config time: 6.9141387939453125e-06
Interferometer config time: 2.86102294921875e-06
ParabolicMirror config time: 1.6689300537109375e-06
DelayGenerator config time: 1.9073486328125e-06
Laser config time: 1.6689300537109375e-06
Periscope ['BladePositioning', 'DRS4', 'test_device1']
Interferometer ['BladePositioning', 'DRS4', 'test_device1']
ParabolicMirror ['BladePositioning', 'DRS4', 'test_device1']
DelayGenerator ['BladePositioning', 'DRS4', 'test_device1']
Laser ['BladePositioning', 'DRS4', 'test_device1']
FocusCamera config time: 1.430511474609375e-06
test_device2 config time: 1.430511474609375e-05
test_device1 config time: 1.8596649169921875e-05
DRS4 config time: 0.0019712448120117188
PlasmaCamHorizontal config time: 1.1920928955078125e-06
ScreenCamera config time: 9.5367431640625e-07
FaradayCup config time: 7.152557373046875e-07
BladePositioning config time: 0.302783727645874
Periscope config time: 4.5299530029296875e-06
Interferometer config time: 3.0994415283203125e-06
ParabolicMirror config time: 1.6689300537109375e-06
DelayGenerator config time: 1.6689300537109375e-06
Laser config time: 1.430511474609375e-06
Choose parameter!!!
Choose parameter!!!
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment