Skip to content
Snippets Groups Projects
Commit bd28070d authored by Alexis GAMELIN's avatar Alexis GAMELIN
Browse files

Update measurements

parent c31f223a
Branches
Tags
No related merge requests found
...@@ -11,14 +11,15 @@ from pythoncontrol.injection import (switch_injection_mode, ...@@ -11,14 +11,15 @@ from pythoncontrol.injection import (switch_injection_mode,
inject_uniform_beam, inject_uniform_beam,
SPM_feedback) SPM_feedback)
from pythoncontrol.chro import (chroma_measurement, from pythoncontrol.chro import (chro_measurement,
chro_analysis) chro_analysis,
get_chro)
from pythoncontrol.fitting import (get_envelope, from pythoncontrol.fitting import (get_envelope,
fit_risetime) fit_risetime)
from pythoncontrol.growth_damp import (take_data_gd, from pythoncontrol.growth_damp import (growth_damp_measurement,
growth_damp, growth_damp_core,
growth_damp_analysis, growth_damp_analysis,
plot_raw, plot_raw,
plot_risetime) plot_risetime)
......
...@@ -7,7 +7,7 @@ import os ...@@ -7,7 +7,7 @@ import os
from time import sleep from time import sleep
from tango import DeviceProxy from tango import DeviceProxy
from pythoncontrol.injection import inject_beam from pythoncontrol.injection import inject_beam
from pythoncontrol.chro import chroma_measurement, chro_analysis from pythoncontrol.chro import get_chro
from pythoncontrol.misc import check_feedback_stoped, get_fbt_device from pythoncontrol.misc import check_feedback_stoped, get_fbt_device
def beam_current_scan_loop(goal_current, def beam_current_scan_loop(goal_current,
...@@ -237,12 +237,7 @@ def beam_current_scan_step(file, ...@@ -237,12 +237,7 @@ def beam_current_scan_step(file,
""" """
if chro_measurement: if chro_measurement:
delta, NuX, NuZ = chroma_measurement(N_step_delta=5, N_meas_tune=1, Pause_meas=2) get_chro(file, **kwargs)
chro = chro_analysis(delta, NuX, NuZ, method="lin", N_step_delta=5, plot=False)
file["chro_delta"] = delta
file["chro_NuX"] = NuX
file["chor_NuY"] = NuZ
file["chro"] = chro
beam_current_scan_loop(goal_current, beam_current_scan_loop(goal_current,
booster_cav, booster_cav,
......
...@@ -13,12 +13,11 @@ from tango import DeviceProxy ...@@ -13,12 +13,11 @@ from tango import DeviceProxy
from scipy.optimize import curve_fit from scipy.optimize import curve_fit
from pythoncontrol.misc import check_feedback_stoped from pythoncontrol.misc import check_feedback_stoped
#%% chroma measurement def chro_measurement(N_step_delta=5,
def chroma_measurement(N_step_delta=5,
delta_change_max=0.002, delta_change_max=0.002,
N_meas_tune=1, N_meas_tune=1,
sleep_time_tune_meas=4): sleep_time_tune_meas=4,
verbose=True):
""" """
Record data for chromaticity measurement. Record data for chromaticity measurement.
...@@ -32,12 +31,15 @@ def chroma_measurement(N_step_delta=5, ...@@ -32,12 +31,15 @@ def chroma_measurement(N_step_delta=5,
Maximum relative energy (delta) variation for the chroma measurement. Maximum relative energy (delta) variation for the chroma measurement.
Maximum allowed is 0.004 = 0.4 % which is default value in MML. Maximum allowed is 0.004 = 0.4 % which is default value in MML.
The default is 0.002. The default is 0.002.
N_meas_tune : TYPE, optional N_meas_tune : int, optional
Number of chroma measurement to do. Number of chroma measurement to do.
The default is 1. The default is 1.
sleep_time_tune_meas : float, optional sleep_time_tune_meas : float, optional
Time to wait before the tune measurement is done. Time to wait before the tune measurement is done.
The default is 4. The default is 4.
verbose : bool, optional
If True, print statements are executed.
The default is True.
Returns Returns
------- -------
...@@ -67,10 +69,12 @@ def chroma_measurement(N_step_delta=5, ...@@ -67,10 +69,12 @@ def chroma_measurement(N_step_delta=5,
check_feedback_stoped() check_feedback_stoped()
if verbose:
print("starting chroma measurement") print("starting chroma measurement")
delta = np.linspace(-delta_change_max, delta_change_max, N_step_delta) delta = np.linspace(-delta_change_max, delta_change_max, N_step_delta)
fRF_0 = RF.frequency fRF_0 = RF.frequency
if verbose:
print("Initial fRF = ", RF.frequency) print("Initial fRF = ", RF.frequency)
delta_fRF_list = delta * alphac * fRF_0 delta_fRF_list = delta * alphac * fRF_0
...@@ -81,9 +85,11 @@ def chroma_measurement(N_step_delta=5, ...@@ -81,9 +85,11 @@ def chroma_measurement(N_step_delta=5,
RF.frequency = fRF_0 + delta_fRF RF.frequency = fRF_0 + delta_fRF
sleep(sleep_time_RF_change) sleep(sleep_time_RF_change)
if verbose:
print("fRF = ", RF.frequency) print("fRF = ", RF.frequency)
while round(RF.frequency,5) != round(fRF_0 + delta_fRF,5): while round(RF.frequency,5) != round(fRF_0 + delta_fRF,5):
sleep(sleep_time_RF_change) sleep(sleep_time_RF_change)
if verbose:
print("fRF = ", RF.frequency) print("fRF = ", RF.frequency)
for j in range(N_meas_tune): for j in range(N_meas_tune):
...@@ -92,19 +98,18 @@ def chroma_measurement(N_step_delta=5, ...@@ -92,19 +98,18 @@ def chroma_measurement(N_step_delta=5,
NuZ[i,j] = tuneZ.Nu NuZ[i,j] = tuneZ.Nu
RF.frequency = fRF_0 RF.frequency = fRF_0
if verbose:
print("chroma measurement done") print("chroma measurement done")
print("Final fRF = ", RF.frequency) print("Final fRF = ", RF.frequency)
return (delta, NuX, NuZ) return (delta, NuX, NuZ)
#%% chroma analysis
def chro_analysis(delta, def chro_analysis(delta,
NuX, NuX,
NuZ, NuZ,
method="lin", method="lin",
plot=True): plot=False,
verbose=True):
""" """
Compute chromaticity from measurement data. Compute chromaticity from measurement data.
...@@ -121,6 +126,9 @@ def chro_analysis(delta, ...@@ -121,6 +126,9 @@ def chro_analysis(delta,
The default is "lin". The default is "lin".
plot : bool, optional plot : bool, optional
If True, plot the fit. If True, plot the fit.
The default is False.
verbose : bool, optional
If True, print statements are executed.
The default is True. The default is True.
Returns Returns
...@@ -170,6 +178,35 @@ def chro_analysis(delta, ...@@ -170,6 +178,35 @@ def chro_analysis(delta,
plt.ylabel('$\\delta nuZ$') plt.ylabel('$\\delta nuZ$')
plt.legend() plt.legend()
if verbose:
print(f"chro is {chro}") print(f"chro is {chro}")
return np.array(chro) return np.array(chro)
def get_chro(file, **kwargs):
"""
Perform chromaticity measurement and analysis, storing results in an HDF5 file.
Parameters
----------
file : h5py.File
HDF5 file/group where the data for this step will be saved.
**kwargs : dict
Additional keyword arguments for measurement and analysis functions.
Valid keys for measurement: 'N_step_delta', 'delta_change_max', 'N_meas_tune', 'sleep_time_tune_meas', 'verbose'.
Valid keys for analysis: 'method', 'plot', 'verbose'.
"""
# Separate kwargs for measurement and analysis
measurement_kwargs = {key: kwargs[key] for key in kwargs if key in ['N_step_delta', 'delta_change_max', 'N_meas_tune', 'sleep_time_tune_meas', 'verbose']}
analysis_kwargs = {key: kwargs[key] for key in kwargs if key in ['method', 'plot', 'verbose']}
# Perform chromaticity measurement with measurement-specific kwargs
delta, NuX, NuZ = chro_measurement(**measurement_kwargs)
chro = chro_analysis(delta, NuX, NuZ, **analysis_kwargs)
# Store the results in the HDF5 file
file.create_dataset("chro_delta", data=delta)
file.create_dataset("chro_NuX", data=NuX)
file.create_dataset("chro_NuZ", data=NuZ)
file.create_dataset("chro", data=chro)
...@@ -10,72 +10,39 @@ from tango import DeviceProxy ...@@ -10,72 +10,39 @@ from tango import DeviceProxy
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import numpy as np import numpy as np
import h5py as hp import h5py as hp
from pythoncontrol.fitting import fit_risetime
from scipy.signal import hilbert from scipy.signal import hilbert
from time import sleep from time import sleep
from pythoncontrol.chro import chroma_measurement, chro_analysis from pythoncontrol.fitting import fit_risetime
from pythoncontrol.misc import check_feedback_stoped, get_fbt_device, get_time_str from pythoncontrol.chro import get_chro
from pythoncontrol.misc import check_feedback_stoped, get_fbt_device
def take_data_gd(window_width, def growth_damp_measurement(file,
window_delay=10, chro_measurement=False,
datasize=4, **kwargs,
file_name=None, ):
N_record=1,
chro_measurement=False):
""" """
Growth damp measurement with some additonal data saved. Growth damp measurement with some additonal data saved.
Parameters Parameters
---------- ----------
window_width : float file : h5py.File
Delay generator window width in [us]. HDF5 file/group where the data for this step will be saved.
Window during which the FBT is off.
window_delay : float, optional
Delay generator window delay in [ns].
Delay of the window during which the FBT is off.
The default is 10.
datasize : int, optional
Data size of the BBFV3 device.
Increasing this value allows to save more turns.
Be careful when increasing this value, ~10 is a good value.
The default is 4.
file_name : str, optional
File name where the data is saved.
If None, is 'growth_damp_{time}.hdf5'
The default is None.
N_record : int, optional
Number of growth damp measurements to save.
The default is 1.
chro_measurement : bool, optional chro_measurement : bool, optional
If True, make de chromaticity measurement before the growth damp one. If True, make de chromaticity measurement before the growth damp one.
The default is False. The default is False.
**kwargs
Returns See get_chro and growth_damp_core kwargs.
-------
file_name : str
File name where the data is saved.
""" """
if chro_measurement: if chro_measurement:
(delta, NuX, NuZ) = chroma_measurement() get_chro(file, **kwargs)
chro_lin = chro_analysis(delta, NuX, NuZ, method="lin", plot=False)
chro_quad = chro_analysis(delta, NuX, NuZ, method="quad", plot=False)
print(f"Chro lin: {chro_lin}")
print(f"Chro quad: {chro_quad}")
remplissage = DeviceProxy("ANS/DG/REMPLISSAGE") remplissage = DeviceProxy("ANS/DG/REMPLISSAGE")
tuneX = DeviceProxy("ans/rf/bbfdataviewer.1-tunex") tuneX = DeviceProxy("ans/rf/bbfdataviewer.1-tunex")
tuneZ = DeviceProxy("ans/rf/bbfdataviewer.2-tunez") tuneZ = DeviceProxy("ans/rf/bbfdataviewer.2-tunez")
phc_C02 = DeviceProxy("ans-c02/dg/phc-emit") phc_C02 = DeviceProxy("ans-c02/dg/phc-emit")
phc_C16 = DeviceProxy("ans-c16/dg/phc-emit") phc_C16 = DeviceProxy("ans-c16/dg/phc-emit")
total_current = np.round(np.sum(remplissage.bunchescurrent),1) # total_current = np.round(np.sum(remplissage.bunchescurrent),1)
# File setup
if file_name is None:
time = get_time_str()
file_name = "growth_damp_" + str(total_current) + "mA_" + time + ".hdf5"
file = hp.File(file_name, "a")
file["filling_pattern_before"] = remplissage.bunchescurrent file["filling_pattern_before"] = remplissage.bunchescurrent
file["tuneX_before"] = tuneX.Nu file["tuneX_before"] = tuneX.Nu
...@@ -84,21 +51,9 @@ def take_data_gd(window_width, ...@@ -84,21 +51,9 @@ def take_data_gd(window_width,
file["emitX_C16_before"] = phc_C16.EmittanceH file["emitX_C16_before"] = phc_C16.EmittanceH
file["emitZ_C02_before"] = phc_C02.EmittanceV file["emitZ_C02_before"] = phc_C02.EmittanceV
file["emitZ_C16_before"] = phc_C16.EmittanceV file["emitZ_C16_before"] = phc_C16.EmittanceV
if chro_measurement:
file["chro_delta"] = delta
file["chro_NuX"] = NuX
file["chro_NuZ"] = NuZ
file["chro_lin"] = chro_lin
file["chro_quad"] = chro_quad
file.close()
growth_damp(window_width=window_width, growth_damp_core(file, **kwargs)
window_delay=window_delay,
datasize=datasize,
file_name=file_name,
N_record=N_record)
file = hp.File(file_name, "a")
file["filling_pattern_after"] = remplissage.bunchescurrent file["filling_pattern_after"] = remplissage.bunchescurrent
file["tuneX_after"] = tuneX.Nu file["tuneX_after"] = tuneX.Nu
file["tuneZ_after"] = tuneZ.Nu file["tuneZ_after"] = tuneZ.Nu
...@@ -108,21 +63,21 @@ def take_data_gd(window_width, ...@@ -108,21 +63,21 @@ def take_data_gd(window_width,
file["emitZ_C16_after"] = phc_C16.EmittanceV file["emitZ_C16_after"] = phc_C16.EmittanceV
file.close() file.close()
return file_name def growth_damp_core(file,
window_width=1,
def growth_damp(window_width,
window_delay=10, window_delay=10,
datasize=4, datasize=4):
file_name=None,
N_record=1):
""" """
Growth damp core function. Growth damp core function.
Parameters Parameters
---------- ----------
window_width : float file : h5py.File
HDF5 file/group where the data for this step will be saved.
window_width : float, optional
Delay generator window width in [us]. Delay generator window width in [us].
Window during which the FBT is off. Window during which the FBT is off.
The default is 1.
window_delay : float, optional window_delay : float, optional
Delay generator window delay in [ns]. Delay generator window delay in [ns].
Delay of the window during which the FBT is off. Delay of the window during which the FBT is off.
...@@ -132,18 +87,6 @@ def growth_damp(window_width, ...@@ -132,18 +87,6 @@ def growth_damp(window_width,
Increasing this value allows to save more turns. Increasing this value allows to save more turns.
Be careful when increasing this value, ~10 is a good value. Be careful when increasing this value, ~10 is a good value.
The default is 4. The default is 4.
file_name : str, optional
File name where the data is saved.
If None, is 'growth_damp_{time}.hdf5'
The default is None.
N_record : int, optional
Number of growth damp measurements to save.
The default is 1.
Returns
-------
file_name : str
File name where the data is saved.
""" """
# Measurement params # Measurement params
...@@ -167,45 +110,37 @@ def growth_damp(window_width, ...@@ -167,45 +110,37 @@ def growth_damp(window_width,
fbt.automaticacquisitionon() fbt.automaticacquisitionon()
sleep(sleep_time_acquisition_on_off) sleep(sleep_time_acquisition_on_off)
# Activate delay channel A
delay.activateChannelA = True
# Stop MNO
selMNOsource_initial = fbt.selMNOsource
fbt.selMNOsource = 0 # no MNO
# File setup # File setup
if file_name is None:
time = get_time_str()
file_name = "growth_damp_" + time + ".hdf5"
file = hp.File(file_name, "a")
file["window_delay"] = window_delay file["window_delay"] = window_delay
file["window_width"] = window_width file["window_width"] = window_width
file["datasize"] = datasize file["datasize"] = datasize
file["N_record"] = N_record file["gainADC0"] = fbt.gainADC0
file["gainADC4"] = fbt.gainADC4
N_data = len(np.float64(fbt.selectedBunchDataADC0)) N_data = len(np.float64(fbt.selectedBunchDataADC0))
for j in range(N_record): file.create_dataset("raw", (h, N_data), dtype="float")
file.create_dataset(f"raw_{j}", (h, N_data), dtype="float")
# Measurment # Measurment setup
delay.pulseDelayChannelA = window_delay delay.pulseDelayChannelA = window_delay
delay.pulseWidthChannelA = window_width delay.pulseWidthChannelA = window_width
sleep(sleep_time_delay_generator_change) sleep(sleep_time_delay_generator_change)
for j in range(N_record): # Stop MNO
if j > 0: selMNOsource_initial = fbt.selMNOsource
fbt.AutomaticAcquisitionON() fbt.selMNOsource = 0 # no MNO
sleep(sleep_time_acquisition_on_off)
fbt.automaticacquisitionoff() # Measurement
sleep(sleep_time_acquisition_on_off) delay.activateChannelA = True
fbt.acquiredataonce()
sleep(0.5 + window_width*1e-6) # value to be tuned
delay.activateChannelA = False
# Save data from buffer
for i in range(h): for i in range(h):
fbt.selectedBunchNumberADC0 = i fbt.selectedBunchNumberADC0 = i
data = np.float64(fbt.selectedBunchDataADC0) data = np.float64(fbt.selectedBunchDataADC0)
file[f"raw_{j}"][i,:] = data file["raw"][i,:] = data
# Get back to nominal # Get back to nominal
delay.activateChannelA = False
fbt.selMNOsource = selMNOsource_initial fbt.selMNOsource = selMNOsource_initial
if datasize != 4: if datasize != 4:
fbt.datasize = 4 # default value for operation fbt.datasize = 4 # default value for operation
...@@ -214,9 +149,7 @@ def growth_damp(window_width, ...@@ -214,9 +149,7 @@ def growth_damp(window_width,
# Tune devices do not work for datasize != 4, so init is needed # Tune devices do not work for datasize != 4, so init is needed
tuneZ.init() tuneZ.init()
tuneX.init() tuneX.init()
file.close()
return file_name
def _avg_mean(signal, window): def _avg_mean(signal, window):
N=len(signal) N=len(signal)
......
...@@ -36,7 +36,8 @@ def get_fbt_device(): ...@@ -36,7 +36,8 @@ def get_fbt_device():
def check_feedback_stoped(SOFB=True, def check_feedback_stoped(SOFB=True,
FOFB=True, FOFB=True,
TuneFB=True): TuneFB=True,
CouplingFB=True):
""" """
Check if the feedback are turned off. Check if the feedback are turned off.
...@@ -51,6 +52,9 @@ def check_feedback_stoped(SOFB=True, ...@@ -51,6 +52,9 @@ def check_feedback_stoped(SOFB=True,
TuneFB : bool, optional TuneFB : bool, optional
If True, check if TuneFB is off. If True, check if TuneFB is off.
The default is True. The default is True.
CouplingFB : bool, optional
If True, check if CouplingFB is off.
The default is True.
Raises Raises
------ ------
...@@ -64,11 +68,14 @@ def check_feedback_stoped(SOFB=True, ...@@ -64,11 +68,14 @@ def check_feedback_stoped(SOFB=True,
service_locker = DeviceProxy("ANS/CA/SERVICE-LOCKER-MATLAB") service_locker = DeviceProxy("ANS/CA/SERVICE-LOCKER-MATLAB")
fofb_watcher = DeviceProxy("ANS/DG/FOFB-WATCHER") fofb_watcher = DeviceProxy("ANS/DG/FOFB-WATCHER")
if service_locker.sofb: if SOFB and service_locker.sofb:
raise ValueError("Stop the SOFB") raise ValueError("Stop the SOFB")
if fofb_watcher.fofbrunning_x or fofb_watcher.fofbrunning_y: if FOFB and (fofb_watcher.fofbrunning_x or fofb_watcher.fofbrunning_y):
raise ValueError("Stop the FOFB") raise ValueError("Stop the FOFB")
if service_locker.isTunexFBRunning or service_locker.isTunezFBRunning: if TuneFB and (service_locker.isTunexFBRunning or service_locker.isTunezFBRunning):
raise ValueError("Stop the tune FB") raise ValueError("Stop the tune FB")
if CouplingFB and service_locker.iscouplingfbrunning:
raise ValueError("Stop the beam size (coupling/white noise) FB")
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment