Commit 623d8808 authored by Yb Tweezer's avatar Yb Tweezer
Browse files

post-hardware upgrade tweaks;

add in-sequence control of shims during probing;

add analog/digital control of TimeBase for tweezer AOD;

add dryrun function to check sequence construction and parameter variation;
parent 74e23aa6
......@@ -13,8 +13,8 @@ import toml
# outdir = DATADIRS.tweezer_atoms.joinpath(timestamp)
_save = True
_label = "mF=p1h_B=5G_probe-scan"
_counter = 11
_label = "adiabatic-ramp"
_counter = 0
date = get_timestamp().split("_")[0].replace("-", "")
datadir = DATADIRS.tweezer_atoms.joinpath(date)
......@@ -24,6 +24,7 @@ while datadir.joinpath(f"{_label}_{_counter:03.0f}").is_dir():
outdir = datadir.joinpath(f"{_label}_{_counter:03.0f}")
comments = """
shifted TimeBase center to 95.0 MHz (fm depth = 12)
"""[1:-1]
# CAMERA OPTIONS
......@@ -47,13 +48,34 @@ flir_config = {
# add a comment for any literal numbers used
## MAIN SEQUENCE PARAMETERS
# general
reps: int = 20 # repeat shots for statistics
clk_freq: float = 10e6 # serial_bits clock frequency; Hz
take_background: bool = False # include a background image
flir_two_shots: bool = False # use the Flir to take two shots
use_cmot_preprobe: bool = False # use the CMOT beams to check imaging conditions
dispenser: float = 4.2 # dispenser current (for book-keeping); A
# repeat shots for statistics
reps: int = 20
# serial_bits clock frequency; Hz
clk_freq: float = 10e6
# include a Flir trigger for a background shot
take_background: bool = False
# use the Flir to take two shots (not inluding background)
flir_two_shots: bool = False
# use the CMOT beams to check imaging conditions
use_cmot_preprobe: bool = False
# dispenser current (for book-keeping); A
dispenser: float = 4.2
# trigger the Andor for the CMOT and truncate the sequence to check alignment
# to the tweezer
check_tweezer_alignment: bool = False
# use *_(PROBE|probe) to control both probe and pre-probe conditions
zip_probes: bool = False
# ramp the tweezer power for a holding block instead of turning it off
tweezer_ramp_hold: bool = True
# timings (not to scale)
#
......@@ -86,9 +108,9 @@ dispenser: float = 4.2 # dispenser current (for book-keeping); A
# | |
# | tau_disperse |
# | |
# --- | tau_all
# --- |
# | |
# | tau_preprobe |
# | tau_preprobe | tau_all
# | |
# --- |
# | |
......@@ -96,6 +118,18 @@ dispenser: float = 4.2 # dispenser current (for book-keeping); A
# | |
# --- |
# | |
# | tau_twzr_dn |
# | |
# --- |
# | |
# | tau_tof / tau_twzr_hold |
# | |
# --- |
# | |
# | tau_twzr_up |
# | |
# --- |
# | |
# | tau_dark_open (andor shutter) |
# | |
# ---------------- <tau_andor> |
......@@ -122,10 +156,14 @@ tau_pause = 0.75e-3 # pause between ncool and load; s
tau_twzr_load = 0e-3 # time to load into tweezers; s
tau_disperse = 30e-3 # wait for CMOT atoms to disperse
TAU_PREPROBE = np.array([0.0e-3]) # hold with CMOT or probe beams at imaging (proxy) frequency
# TAU_PREPROBE = np.array([0.5, 1.0, 2.0, 5.0, 10.0, 50.0, 100.0, 200.0, 300.0, 400.0, 500.0]) * 1e-3
# TAU_PREPROBE = np.array([0.0e-3, 1.0e-3, 5.0e-3, 10.0e-3, 20.0e-3, 30.0e-3])
TAU_PP = np.array([0.0e-3]) # parity projection pulse time; s
# TAU_TOF = np.array([0.0, 1.0, 5.0, 30.0, 50.0, 100.0]) * 1e-6 # tweezer release-recapture time; s
TAU_TOF = np.array([0.0e-6])
TAU_TWZR_HOLD = np.array([20.0]) * 1e-3 # hold time for tweezer ramp; s
tau_dark_open = 27e-3 # shutter opening time for EMCCD; s
TAU_PROBE = np.array([100e-3]) # probe beam time; s
# TAU_PROBE = np.array([0.5, 1.0, 2.0, 5.0, 10.0, 50.0, 100.0, 200.0, 300.0, 400.0, 500.0]) * 1e-3
tau_image = TAU_PROBE.max() # EMCCD exposure time; s
tau_dark_close = 40e-3 # shutter closing time for EMCCD; s
......@@ -135,22 +173,25 @@ tau_flir_second = tau_twzr_load + 5e-3 # second Flir shot rel. to end of pause a
TAU_ANDOR = np.array([0.0e-3]) # EMCCD camera time relative to end of dark period; s
# coil settings
SHIMS_FB = np.linspace(1.250, 1.250, 1) # Front/Back shim scans: 1.22; +1.2 for 174
SHIMS_LR = np.linspace(-0.22, -0.22, 1) # Left/Right shim scans: 0.20; -0.2 for 174
SHIMS_UD = np.linspace(0.300, 0.300, 1) # Up/Down shim scans: 0.57; +0.4 for 174
SHIMS_FB = np.linspace(+1.155, +1.155, 1) # Front/Back shim scans: 1.25; +1.2 for 174
SHIMS_LR = np.linspace(-0.350, -0.350, 1) # Left/Right shim scans: -0.22; -0.2 for 174
SHIMS_UD = np.linspace(+0.645, +0.645, 1) # Up/Down shim scans: 0.30; +0.4 for 174
B_blue = int(441815) # blue MOT gradient setting
B_green = int(44182 * 1.25) # 174: 1.25 -> 1.1
bits_Bset = int(20) # number of bits in a servo setting
bits_DACset = int(4) # number of bits in a DAC-mode setting
B_COMP = np.linspace(B_green, B_green * 1.8, T_COMP.shape[0]) # compression ramp values
shims_ud_pp = 0 # bias field for parity projection: B = 0.4 * 4.92 * V
SHIMS_UD_PROBE = np.linspace(2.54, 2.54, 1) # bias field during probing (imaging) time: B = 0.4 * 4.92 * V
SHIMS_UD_PREPROBE = np.linspace(0.00, 0.00, 1) # bias field during pre-probing time: B = 0.4 * 4.92 * V
SHIMS_UD_PP = np.linspace(0.0, 0.0, 1) # bias field for parity projection: B = 0.4 * 4.92 V
SHIMS_UD_PROBE = np.linspace(0.00, 0.00, 1) # bias field during probing (imaging) time: B = 0.4 * 4.92 * V
# detunings
DET_PREPROBE = np.linspace(3.4, 3.4, 1) # preprobe imaging conditions proxy using CMOT or probe beams (rel. to AOM center); MHz
DET_PROBE = np.linspace(7.0, 8.5, 16) # probe beam detuning for imaging (rel. to AOM center); MHz
DET_LOAD = np.linspace(-0.0, +0.0, 1) # green MOT detuning for tweezer loading (rel. to CMOT); MHz
DET_PP = np.linspace(-3.58, +0.42, 1) # green MOT detuning for partity projection (rel. to CMOT); MHz
DET_PREPROBE = np.linspace(+5.00, +5.00, 1) # preprobe imaging conditions proxy using CMOT/probe beams (rel. to 90.0); MHz
# DET_PREPROBE = np.array([0.0])
DET_PROBE = np.linspace(+5.00, +5.00, 1) # probe beam detuning for imaging (rel. to AOM center); MHz
# DET_PROBE = np.linspace(-2.00, +10.00, 25)
DET_LOAD = np.linspace(-0.00, +0.00, 1) # green MOT detuning for tweezer loading (rel. to CMOT); MHz
DET_PP = np.linspace(-2.00, +1.60, 1) # green MOT detuning for partity projection (rel. to CMOT); MHz
det_556_tweezer = 3.68 # detuning on the 556 tweezer (probe) path (rel. to AOM center); MHz
## CMOT RAMP PARAMETERS
......@@ -158,7 +199,6 @@ det_556_tweezer = 3.68 # detuning on the 556 tweezer (probe) path (rel. to AOM c
ramp_N = 1000 # number of steps in the ramp
# timings
tau_ref = -10e-3 # lead time for mogtable to start up; s
tau_ramp = 20e-3 # start of ramp after t0; s
tau_rampdur = 30e-3 # ramp duration; s
......@@ -169,16 +209,56 @@ nu_ramp = 3.58 # extent of ramp; MHz
# power parameters
p_ramp_beg = 29.0 # start of ramp; dBm
p_ramp_end = -11.0 # end of ramp; dBm
p_preprobe = 14.0 # power in pre-probe pulse; dBm
p_probe = 14.0 # power in probe beam AOMs; dBm
p_preprobe = 27.0 # power in pre-probe pulse; dBm
p_probe = 24.0 # power in probe beam AOMs; dBm
p_556_tweezer = -10.0 # power in the 556 tweezer (probe) AOM; dBm
p_pp = 17.0 # parity projection pulse AOM (CMOT) power; dBm
p_pp = 6.0 # parity projection pulse AOM (CMOT) power; dBm
# derived arrays
RAMP_T = t0 + np.linspace(tau_ramp, tau_ramp + tau_rampdur, ramp_N + 1)
RAMP_F = np.linspace(f_ramp, f_ramp + nu_ramp, ramp_N + 1)
RAMP_P = np.linspace(p_ramp_beg, p_ramp_end, ramp_N + 1)
## TWEEZER RAMP PARAMETERS
# general
twzr_N = 100 # number of steps in the ramp
# timings
tau_twzr_dn = 2e-3 # ramp-down time; s
tau_twzr_up = 2e-3 # ramp-up time; s
# hold power
p_twzr_init = 29.99
P_TWZR_HOLD = np.linspace(0.2, 29.99, 10)
# derived arrays
TWZR_T_DN = np.linspace(0.0, tau_twzr_dn, twzr_N)
TWZR_T_UP = np.linspace(0.0, tau_twzr_up, twzr_N)
if check_tweezer_alignment:
tau_pause = 0.0
tau_twzr_load = 0.0
tau_disperse = 0.0
TAU_PREPROBE = np.array([0.0])
TAU_PP = np.array([0.0])
TAU_TOF = np.array([0.0])
TAU_PROBE = np.array([0.0])
tau_dark_open = 0.0
tau_image = 0.0
tau_dark_close = 0.0
TAU_ANDOR = np.array([-10e-3])
tau_flir = 0.0
if zip_probes:
p_preprobe = p_probe
if tweezer_ramp_hold:
TAU_TOF = np.array([0.0])
else:
tau_twzr_dn = 0.0
TAU_TWZR_HOLD = np.array([0.0])
tau_twzr_up = 0.0
# book-keeping info
params = {
k.lower(): float(v) if isinstance(v, float)
......@@ -197,11 +277,16 @@ def make_sequence(
shims_fb: float,
shims_lr: float,
shims_ud: float,
shims_ud_preprobe: float,
shims_ud_pp: float,
shims_ud_probe: float,
tau_preprobe: float,
tau_pp: float,
tau_tof: float,
tau_twzr_hold: float,
tau_probe: float,
tau_andor: float,
p_twzr_hold: float,
) -> SuperSequence:
tau_all = ( # main sequence time; s
tau_ncool
......@@ -209,10 +294,17 @@ def make_sequence(
+ tau_twzr_load
+ tau_preprobe
+ tau_pp
+ tau_tof
+ tau_twzr_dn
+ tau_twzr_hold
+ tau_twzr_up
+ tau_dark_open
+ tau_image
+ tau_dark_close
)
if zip_probes:
det_preprobe = det_probe
shims_ud_preprobe = shims_ud_probe
SEQ = SuperSequence(
outdir.joinpath("sequences"),
"_".join(f"{k.replace('_', '-'):s}={v:.5f}" for k, v in locals().copy().items()),
......@@ -235,6 +327,10 @@ def make_sequence(
+ tau_disperse
+ tau_preprobe
+ tau_pp
+ tau_tof
+ tau_twzr_dn
+ tau_twzr_hold
+ tau_twzr_up
+ tau_dark_open
+ tau_andor - 27e-3 # shutter time
),
......@@ -433,7 +529,7 @@ def make_sequence(
Event.digital1(**C.mot3_green_aom, s=0)
@ (t0 + tau_ncool + tau_pause + tau_twzr_load + tau_disperse)
])
).with_color("k"),
).with_color("C7"),
"Parity projection": (Sequence()
+ Sequence([ # apply parity projection pulse
......@@ -459,7 +555,7 @@ def make_sequence(
).with_color("C6"),
"MOT beams off": (Sequence()
+ Sequence([ # detune and depower the MOT beams for imaging
+ Sequence([ # detune and depower the MOT beams for TOF + imaging
Event.analog(
**C.mot3_green_aom_fm, s=MOT3_GREEN_AOM_FM(89.0)
) @ (t0
......@@ -511,6 +607,10 @@ def make_sequence(
+ tau_disperse
+ tau_preprobe
+ tau_pp
+ tau_tof
+ tau_twzr_dn
+ tau_twzr_hold
+ tau_twzr_up
+ tau_dark_open
),
tau_probe,
......@@ -525,6 +625,10 @@ def make_sequence(
+ tau_disperse
+ tau_preprobe
+ tau_pp
+ tau_tof
+ tau_twzr_dn
+ tau_twzr_hold
+ tau_twzr_up
+ tau_dark_open
),
Event.analog(**C.probe_green_aom_am, s=PROBE_GREEN_AOM_AM(p_probe))
......@@ -535,6 +639,10 @@ def make_sequence(
+ tau_disperse
+ tau_preprobe
+ tau_pp
+ tau_tof
+ tau_twzr_dn
+ tau_twzr_hold
+ tau_twzr_up
+ tau_dark_open
),
])
......@@ -547,6 +655,10 @@ def make_sequence(
+ tau_disperse
+ tau_preprobe
+ tau_pp
+ tau_tof
+ tau_twzr_dn
+ tau_twzr_hold
+ tau_twzr_up
+ tau_dark_open
- 4.5e-3 # 4.5ms delay
)
......@@ -560,6 +672,10 @@ def make_sequence(
+ tau_disperse
+ tau_preprobe
+ tau_pp
+ tau_tof
+ tau_twzr_dn
+ tau_twzr_hold
+ tau_twzr_up
+ tau_dark_open
),
Event.analog(**C.shim_coils_ud, s=0.0)
......@@ -570,6 +686,10 @@ def make_sequence(
+ tau_disperse
+ tau_preprobe
+ tau_pp
+ tau_tof
+ tau_twzr_dn
+ tau_twzr_hold
+ tau_twzr_up
+ tau_dark_open
+ tau_probe
),
......@@ -645,9 +765,9 @@ def make_sequence(
+ tau_disperse
- 4.5e-3 # 4.5ms delay
)
] if shims_ud_probe < 0.0 else list())
] if shims_ud_preprobe < 0.0 else list())
+ Sequence([
Event.analog(**C.shim_coils_ud, s=abs(shims_ud_probe))
Event.analog(**C.shim_coils_ud, s=abs(shims_ud_preprobe))
@ (t0
+ tau_ncool
+ tau_pause
......@@ -662,9 +782,47 @@ def make_sequence(
+ tau_disperse
+ tau_preprobe
),
] if shims_ud_probe != 0.0 else list())
] if shims_ud_preprobe != 0.0 else list())
).with_color("g")
if tau_tof > 0.0 and not tweezer_ramp_hold:
SEQ["TOF"] = Sequence.digital_pulse(
*C.tweezer_aod,
(t0
+ tau_ncool
+ tau_pause
+ tau_twzr_load
+ tau_disperse
+ tau_preprobe
+ tau_pp
),
tau_tof
).with_color("k")
if tau_twzr_hold > 0.0 and tweezer_ramp_hold:
t1 = (t0
+ tau_ncool
+ tau_pause
+ tau_twzr_load
+ tau_disperse
+ tau_preprobe
+ tau_pp
)
TWZR_P_DN = np.linspace(p_twzr_init, p_twzr_hold, twzr_N)
TWZR_P_UP = np.linspace(p_twzr_hold, p_twzr_init, twzr_N)
SEQ["Tweezer ramp"] = (Sequence()
+ Sequence([
Event.analog(**C.tweezer_aod_am, s=TWEEZER_AOD_AM(p))
@ (t1 + t)
for t, p in zip(TWZR_T_DN, TWZR_P_DN)
])
+ Sequence([
Event.analog(**C.tweezer_aod_am, s=TWEEZER_AOD_AM(p))
@ (t1 + tau_twzr_dn + tau_twzr_hold + t)
for t, p in zip(TWZR_T_UP, TWZR_P_UP)
])
).with_color("r")
SEQ["Sequence"] = ( # dummy sequence; ensures that EW backend stays in-sequence
Sequence.digital_hilo(
*C.dummy,
......@@ -719,22 +877,15 @@ class NarrowCoolingTweezerAlignment(Controller):
self.comp.set_defaults().def_digital(*C.probe_green_sh, 1)
self.tb = TIMEBASE.connect()
self.tb.set_amplitude(p_probe)
self.tb.set_frequency(95.0).set_amplitude(p_probe)
self.N_ew = np.prod([
len(X) for X in [
DET_LOAD,
DET_PREPROBE,
DET_PP,
DET_PROBE,
SHIMS_FB,
SHIMS_LR,
SHIMS_UD,
SHIMS_UD_PROBE,
TAU_PREPROBE,
TAU_PP,
TAU_PROBE,
TAU_ANDOR,
DET_LOAD, DET_PREPROBE, DET_PP, DET_PROBE,
SHIMS_FB, SHIMS_LR, SHIMS_UD,
SHIMS_UD_PREPROBE, SHIMS_UD_PP, SHIMS_UD_PROBE,
TAU_PREPROBE, TAU_PP, TAU_TOF, TAU_TWZR_HOLD, TAU_PROBE, TAU_ANDOR,
P_TWZR_HOLD,
]
])
......@@ -752,8 +903,10 @@ class NarrowCoolingTweezerAlignment(Controller):
make_sequence(*X)
for X in product(
DET_LOAD, DET_PREPROBE, DET_PP, DET_PROBE,
SHIMS_FB, SHIMS_LR, SHIMS_UD, SHIMS_UD_PROBE,
TAU_PREPROBE, TAU_PP, TAU_PROBE, TAU_ANDOR,
SHIMS_FB, SHIMS_LR, SHIMS_UD,
SHIMS_UD_PREPROBE, SHIMS_UD_PP, SHIMS_UD_PROBE,
TAU_PREPROBE, TAU_PP, TAU_TOF, TAU_TWZR_HOLD, TAU_PROBE, TAU_ANDOR,
P_TWZR_HOLD,
)
)
......@@ -785,6 +938,12 @@ class NarrowCoolingTweezerAlignment(Controller):
.clear()
)
print("")
T = timeit.default_timer() - t0
print(
f" total elapsed time: {T:.2f} s"
f"\n average time per shot: {T / self.TOT:.2f} s"
)
if take_background:
print("background")
(self.comp
......@@ -793,12 +952,6 @@ class NarrowCoolingTweezerAlignment(Controller):
.clear()
)
T = timeit.default_timer() - t0
print(
f" total elapsed time: {T:.2f} s"
f"\n average time per shot: {T / self.TOT:.2f} s"
)
self.comp.clear().disconnect()
self.tb.disconnect()
......@@ -820,32 +973,55 @@ class NarrowCoolingTweezerAlignment(Controller):
def cmd_visualize(self, *args):
seq = make_sequence(
DET_LOAD.mean(), DET_PREPROBE.mean(), DET_PP.mean(), DET_PROBE.mean(),
SHIMS_FB.mean(), SHIMS_LR.mean(), SHIMS_UD.mean(), SHIMS_UD_PROBE.mean(),
TAU_PREPROBE.mean(), TAU_PP.mean(), TAU_PROBE.mean(), TAU_ANDOR.mean(),
SHIMS_FB.mean(), SHIMS_LR.mean(), SHIMS_UD.mean(),
SHIMS_UD_PREPROBE.mean(), SHIMS_UD_PREPROBE.mean(), SHIMS_UD_PROBE.mean(),
TAU_PREPROBE.mean(), TAU_PP.mean(), TAU_TOF.mean(), TAU_TWZR_HOLD.mean(), TAU_PROBE.mean(), TAU_ANDOR.mean(),
P_TWZR_HOLD.mean(),
)
try:
tmin, tmax = float(args[0]), float(args[1])
except IndexError:
tmin, tmax = 0.0, seq.max_time()
P = seq.draw_detailed()
for t in np.cumsum([
t0,
tau_ncool,
tau_pause,
tau_twzr_load,
tau_disperse,
TAU_PREPROBE.mean(),
TAU_PP.mean(),
tau_dark_open,
TAU_PROBE.mean()
]):
for t in np.cumsum(
[
t0,
tau_ncool,
tau_pause,
tau_twzr_load,
tau_disperse,
TAU_PREPROBE.mean(),
TAU_PP.mean(),
]
+ (
[TAU_TOF.mean()] if not tweezer_ramp_hold
else [tau_twzr_dn, TAU_TWZR_HOLD.mean(), tau_twzr_up]
)
+ [
tau_dark_open,
TAU_PROBE.mean()
]
):
P.axvline(t, color="r", linestyle="-", linewidth=0.4)
for t in np.cumsum([t0, tau_ramp, tau_rampdur]):
P.axvline(t, color="g", linestyle="--", linewidth=0.4)
for t in [
t0 + tau_comp,
t0 + tau_ncool + tau_pause + tau_flir,
t0 + tau_ncool + tau_pause + tau_twzr_load + tau_disperse + TAU_PREPROBE.mean() + TAU_PP.mean() + tau_dark_open + TAU_ANDOR.mean(),
(t0
+ tau_ncool
+ tau_pause
+ tau_twzr_load
+ tau_disperse
+ TAU_PREPROBE.mean()
+ TAU_PP.mean()
+ (
TAU_TOF.mean() if not tweezer_ramp_hold
else (tau_twzr_dn + TAU_TWZR_HOLD.mean() + tau_twzr_up)
)
+ tau_dark_open
+ TAU_ANDOR.mean()
),
]:
P.axvline(t, color="b", linestyle=":", linewidth=0.4)
(P
......@@ -859,7 +1035,7 @@ class NarrowCoolingTweezerAlignment(Controller):
self._perform_actions("dryrun_", args)
def dryrun_sequence(self, *args):
print("DRY RUN")
print("[control] DRY RUN")
if _save:
if not datadir.is_dir():
print(f"[dryrun] :: mkdir -p {datadir}")
......@@ -868,25 +1044,17 @@ class NarrowCoolingTweezerAlignment(Controller):
print("[dryrun] write params.toml")
print("[dryrun] write comments.txt")
t0 = timeit.default_timer()
for rep in range(reps):
for i, seq in enumerate(self.ssequences()):
print(self.fmt.format(
rep + 1, i + 1,
100.0 * (
sum(q * nnq for q, nnq in zip([rep, i], self.NN)) + 1
) / self.TOT
), end="", flush=True)
print("")
if take_background:
print("background")
seq = next(self.ssequences())
print(f"[dryrun] found {self.TOT:.0f} loop iterations to perform")
T = timeit.default_timer() - t0
print(
f" total elapsed time: {T:.2f} s"
f"\n average time per shot: {T / self.TOT:.2f} s"
f" total elapsed time: X.XX s"
f"\n average time per shot: X.XX s"
)
if take_background:
print("[dryrun] background")
self.comp.clear().disconnect()
self.tb.disconnect()
......
Supports Markdown
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