make proc sweep general
This commit is contained in:
parent
b1ec523aaa
commit
14ca15e96d
@ -43,6 +43,7 @@ from .measurement import measure_spectrum as _measure_spectrum, set_offsets_lase
|
||||
from .utility.prsdata import PrsData, plot_spectrum
|
||||
from .utility.config_file import ConfigFile
|
||||
from .utility.device_select import select_device_interactive, connect_device_from_config_or_interactive
|
||||
from .utility import duration_to_string
|
||||
from .update_funcs import Monitor
|
||||
|
||||
import logging
|
||||
@ -170,6 +171,7 @@ def measure_spectrum(metadata:dict={},
|
||||
# measure/set offset
|
||||
full_scale_voltage = lockin_params["sensitivity_volt"]
|
||||
def set_offsets(name):
|
||||
# TODO: use multithreading and queues
|
||||
shutter.close()
|
||||
plt_monitor.set_fig_title(f"Measuring baseline with lamp off")
|
||||
R_offset_fs, phase_offset_deg = set_offsets_laser_only(lockin, shutter, measurement_params["wait_time_s"])
|
||||
@ -236,23 +238,24 @@ def measure_spectrum(metadata:dict={},
|
||||
|
||||
|
||||
def sweep_ref():
|
||||
wavelenghts = [500, 550, 650, 660, 670, 680]
|
||||
frequencies = list(range(27, 500, 5))
|
||||
frequencies = [111, 444]
|
||||
wavelenghts = [500, 535, 565, 580, 700]
|
||||
frequencies = list(range(27, 500, 2))
|
||||
lockin_params = {
|
||||
"time_constant_s": 10,
|
||||
}
|
||||
measurement_params = {
|
||||
"wavelengths_nm": wavelenghts,
|
||||
}
|
||||
time_est = len(frequencies) * get_time_estimate(lockin_params=lockin_params, measurement_params=measurement_params, offset_with_laser_only=True, extra_wait_time_s=10)
|
||||
print(f"Estimated time: {time_est}")
|
||||
return
|
||||
time_est = 1.15 * len(frequencies) * get_time_estimate(lockin_params=lockin_params, measurement_params=measurement_params, offset_with_laser_only=True, extra_wait_time_s=10)
|
||||
print(f"Estimated time: {duration_to_string(time_est)}")
|
||||
t_start = time.time()
|
||||
for f in frequencies:
|
||||
dirname = f"2025-05-07_f-scan_f={f}_Hz"
|
||||
lockin_params["frequency"] = f
|
||||
dirname = f"2025-05-09_f-scan_f={f}_Hz"
|
||||
lockin_params["frequency_Hz"] = f
|
||||
measure_spectrum(lockin_params=lockin_params, measurement_params=measurement_params, dirname=dirname, name="Frequency scan $f = {f}$ Hz")
|
||||
plt.close('all')
|
||||
duration = time.time() - t_start
|
||||
print(f"Measurement took {duration_to_string(duration)} (estimate was {duration_to_string(time_est)})")
|
||||
|
||||
# DATA
|
||||
def data_load(dirname:str) -> tuple[np.ndarray, dict]:
|
||||
|
BIN
prsctrl/tests/__pycache__/spectrum_sweeps.cpython-311.pyc
Normal file
BIN
prsctrl/tests/__pycache__/spectrum_sweeps.cpython-311.pyc
Normal file
Binary file not shown.
Binary file not shown.
87
prsctrl/tests/spectrum_sweeps.py
Normal file
87
prsctrl/tests/spectrum_sweeps.py
Normal file
@ -0,0 +1,87 @@
|
||||
from prsctrl.utility.prsdata import PrsData
|
||||
import os
|
||||
import re
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
def process_results(
|
||||
data_dir,
|
||||
dir_regex=r".*",
|
||||
out_dir=None,
|
||||
get_varied_param=lambda data: data.metadata["lock-in_settings"]["frequency_Hz"],
|
||||
fig_suptitle="Frequency scan: <qty>",
|
||||
xlabel="$f$ [Hz]",
|
||||
what=["theta", "stheta", "dR_R", "sdR_R"],
|
||||
):
|
||||
"""
|
||||
Process the results of several spectra recorded with one varying measurement or lock-in parameter.
|
||||
|
||||
:param data_dir: Directory containing all data directories of the individual files
|
||||
:param dir_regex: Regex for filtering data directories
|
||||
:param out_dir: Directory into which the plots are saved
|
||||
:param get_varied_param: lambda function getting the varied parameter value from a loaded PrsData object
|
||||
:param fig_suptitle: Figure suptitle, <qty> will be replaced by the name of the quantity
|
||||
:param xlabel: xlabel for the varied parameter
|
||||
:param what: For which quantities to create plots
|
||||
:return:
|
||||
"""
|
||||
data_dir = os.path.expanduser(data_dir)
|
||||
if out_dir is None:
|
||||
out_dir = data_dir
|
||||
paths = os.listdir(data_dir)
|
||||
data_dirs = []
|
||||
for p in paths:
|
||||
full_path = os.path.join(data_dir, p)
|
||||
if not os.path.isdir(full_path): continue
|
||||
m = re.fullmatch(dir_regex, p)
|
||||
if m:
|
||||
data_dirs.append(full_path)
|
||||
else:
|
||||
print(f"Unmatched directory {p}")
|
||||
assert len(data_dirs) > 0
|
||||
data_dirs.sort()
|
||||
|
||||
varied_params = []
|
||||
data = {}
|
||||
shape = None
|
||||
wls = None
|
||||
for d in data_dirs:
|
||||
print(f"Getting data from {d}")
|
||||
pd = PrsData(load_data_path=d)
|
||||
# f = pd.metadata["lock-in_settings"]["frequency_Hz"]
|
||||
varied_param = get_varied_param(pd)
|
||||
# print(d, f)
|
||||
sdata = pd.get_spectrum_data()
|
||||
print(pd.wavelengths)
|
||||
print(pd.data.keys())
|
||||
if wls is None: wls = sdata[:,0]
|
||||
if shape is None: shape = sdata.shape
|
||||
else:
|
||||
if shape != sdata.shape:
|
||||
print(f"ERROR Shape mismatch for param={varied_param}: {shape} != {sdata.shape}")
|
||||
continue
|
||||
# raise ValueError(f"Shape mismatch for {d}: {shape} != {sdata.shape}")
|
||||
varied_params.append(varied_param)
|
||||
data[varied_param] = sdata
|
||||
data_per_wl_and_vp = np.empty((shape[0], len(varied_params), shape[1]))
|
||||
varied_params.sort()
|
||||
for i in range(shape[0]):
|
||||
for j, f in enumerate(varied_params):
|
||||
data_per_wl_and_vp[i, j, :] = data[f][i,:]
|
||||
print(f"Found wavelengths: {wls}")
|
||||
n_cols = 2
|
||||
n_rows = wls.shape[0] // n_cols + wls.shape[0] % n_cols
|
||||
for qty in what:
|
||||
fig, axs = plt.subplots(n_rows, n_cols, figsize=(8, 8))
|
||||
axs = axs.flatten()
|
||||
qty_idx = PrsData.default_spectrum_columns.index(qty)
|
||||
fig.suptitle(fig_suptitle.replace("<qty>", PrsData.key_names[qty]))
|
||||
for i, wl in enumerate(wls):
|
||||
ax = axs[i]
|
||||
ax.set_xlabel(xlabel)
|
||||
ax.set_ylabel(PrsData.labels[qty])
|
||||
ax.plot(varied_params, data_per_wl_and_vp[i, :, qty_idx])
|
||||
ax.set_title(f"$\\lambda = {wl}$ nm")
|
||||
fig.tight_layout()
|
||||
fig.savefig(os.path.join(out_dir, f"result_{qty}.pdf"))
|
||||
print(varied_params)
|
@ -1,65 +0,0 @@
|
||||
from prsctrl.utility.prsdata import PrsData
|
||||
import os
|
||||
import re
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
def process_results(data_dir, dir_regex=r"202.-..-.._f-scan_f=(\d+)_Hz", out_dir=None):
|
||||
data_dir = os.path.expanduser(data_dir)
|
||||
if out_dir is None:
|
||||
out_dir = data_dir
|
||||
paths = os.listdir(data_dir)
|
||||
data_dirs = []
|
||||
for p in paths:
|
||||
full_path = os.path.join(data_dir, p)
|
||||
if not os.path.isdir(full_path): continue
|
||||
m = re.fullmatch(dir_regex, p)
|
||||
if m:
|
||||
data_dirs.append(full_path)
|
||||
else:
|
||||
print(f"Unmatched directory {p}")
|
||||
assert len(data_dirs) > 0
|
||||
data_dirs.sort()
|
||||
|
||||
frequencies = []
|
||||
data = {}
|
||||
shape = None
|
||||
wls = None
|
||||
for d in data_dirs:
|
||||
print(f"Getting data from {d}")
|
||||
pd = PrsData(load_data_path=d)
|
||||
f = pd.metadata["lock-in_settings"]["frequency_Hz"]
|
||||
# print(d, f)
|
||||
sdata = pd.get_spectrum_data()
|
||||
print(pd.wavelengths)
|
||||
print(pd.data.keys())
|
||||
if wls is None: wls = sdata[:,0]
|
||||
if shape is None: shape = sdata.shape
|
||||
else:
|
||||
if shape != sdata.shape:
|
||||
print(f"ERROR Shape mismatch for f={f}: {shape} != {sdata.shape}")
|
||||
continue
|
||||
# raise ValueError(f"Shape mismatch for {d}: {shape} != {sdata.shape}")
|
||||
frequencies.append(f)
|
||||
data[f] = sdata
|
||||
data_per_wl_and_f = np.empty((shape[0], len(frequencies), shape[1]))
|
||||
frequencies.sort()
|
||||
for i in range(shape[0]):
|
||||
for j, f in enumerate(frequencies):
|
||||
data_per_wl_and_f[i, j, :] = data[f][i,:]
|
||||
print(f"Found wavelengths: {wls}")
|
||||
n_cols = 2
|
||||
for qty in ["theta", "stheta", "dR_R", "sdR_R"]:
|
||||
fig, axs = plt.subplots(wls.shape[0]//n_cols, n_cols, sharex=True, figsize=(8, 8))
|
||||
axs = axs.flatten()
|
||||
qty_idx = PrsData.default_spectrum_columns.index(qty)
|
||||
fig.suptitle(f"Frequency scan: {PrsData.key_names[qty]}")
|
||||
axs[-1].set_xlabel("Modulation Frequency $f$ [Hz]")
|
||||
for i, wl in enumerate(wls):
|
||||
ax = axs[i]
|
||||
ax.set_ylabel(PrsData.labels[qty])
|
||||
ax.plot(frequencies, data_per_wl_and_f[i, :, qty_idx])
|
||||
ax.set_title(f"$\\lambda = {wl}$ nm")
|
||||
fig.tight_layout()
|
||||
fig.savefig(out_dir + f"result_{qty}.pdf")
|
||||
print(frequencies)
|
@ -0,0 +1,25 @@
|
||||
timedelta = [("d", 24*3600), ("h", 3600), ("m", 60), ("s", 1)]
|
||||
def duration_to_string(duration: float) -> str:
|
||||
"""
|
||||
Convert a duration in seconds to a string of the form "<days>d <hours>h <minutes>m <seconds>s"
|
||||
where only the largest units are included.
|
||||
Parameters
|
||||
----------
|
||||
duration: float
|
||||
Duration in seconds.
|
||||
|
||||
Returns
|
||||
-------
|
||||
String representation of the duration.
|
||||
"""
|
||||
include = False
|
||||
s = ""
|
||||
sign = 1 if duration > 0 else -1
|
||||
time_left = abs(int(duration))
|
||||
for i, (unit, unit_seconds) in enumerate(timedelta):
|
||||
t = int(time_left / unit_seconds)
|
||||
if t != 0 or include or unit == "s":
|
||||
s += f"{sign*t:02}{unit} "
|
||||
include = True
|
||||
time_left %= unit_seconds
|
||||
return s.strip()
|
Binary file not shown.
Binary file not shown.
@ -162,8 +162,11 @@ class PrsData:
|
||||
"dR": r"$\Delta R$ [V]",
|
||||
"R": r"$R$ [V]",
|
||||
"theta": r"$\theta$ [°]",
|
||||
"sdR_R": r"$\sigma_{\Delta R/R}$",
|
||||
"sdR": r"$\sigma_{\Delta R}$ [V]",
|
||||
"sR": r"$\sigma_R$ [V]",
|
||||
"stheta": r"$\sigma_\theta$ [°]",
|
||||
}
|
||||
labels |= {f"s{k}": f"$\sigma_{{{v[1:]}}}" for k, v in labels.items()}
|
||||
def get_spectrum_data(self, wavelengths=None, keys=None) -> np.ndarray:
|
||||
"""
|
||||
Return the spectral data for the specified keys and wavelengths.
|
||||
|
Loading…
x
Reference in New Issue
Block a user