diff --git a/pulse_lib/tests/acquire/test_downsampling_with_t_measure_loop.py b/pulse_lib/tests/acquire/test_downsampling_with_t_measure_loop.py
new file mode 100644
index 0000000000000000000000000000000000000000..c9e90eb2ac23f1e427bff05505be3ad616b14b49
--- /dev/null
+++ b/pulse_lib/tests/acquire/test_downsampling_with_t_measure_loop.py
@@ -0,0 +1,45 @@
+
+from pulse_lib.tests.configurations.test_configuration import context
+import pulse_lib.segments.utility.looping as lp
+
+#%%
+
+def test():
+    pulse = context.init_pulselib(n_gates=6, n_qubits=4, n_sensors=2)
+
+    t_measure = lp.linspace(1000, 5_000, 5, name='t_measure', axis=0)
+
+    s = pulse.mk_segment()
+
+    s.SD1.acquire(100, -1)
+    s.P1.add_block(100, 1000, 500)
+    s.wait(t_measure)
+
+    context.plot_segments([s], index=(0,0))
+
+    sequence = pulse.mk_sequence([s])
+    sequence.n_rep = 10
+    sequence.set_acquisition(sample_rate=1000e3)
+    context.add_hw_schedule(sequence)
+    m_param = sequence.get_measurement_param()
+    print(m_param.setpoints)
+
+    for t in sequence.t_measure.values:
+        sequence.t_measure(t)
+        context.plot_awgs(sequence, ylim=(-0.100,0.100))
+        # data must be retrieved from digitizer.
+        data = m_param()
+        print(data)
+
+    ds = context.run('downsampling_t_measure_loop', sequence, m_param)
+
+    return ds
+
+
+#%%
+if __name__ == '__main__':
+    import numpy as np
+    ds = test()
+#    print(np.mean(ds.SD1_1, axis=2))
+#    print(np.mean(ds.SD1_2, axis=2))
+#    print(np.mean(ds.SD1_3, axis=2))
diff --git a/pulse_lib/tests/acquire/test_measurement_data.py b/pulse_lib/tests/acquire/test_measurement_data.py
new file mode 100644
index 0000000000000000000000000000000000000000..d8f93949637a53016c8695319019e5c4da8d6868
--- /dev/null
+++ b/pulse_lib/tests/acquire/test_measurement_data.py
@@ -0,0 +1,52 @@
+
+from pulse_lib.tests.configurations.test_configuration import context
+
+#%%
+def test1():
+    pulse = context.init_pulselib(n_gates=2, n_sensors=2)
+
+    s = pulse.mk_segment()
+
+    s.P1.add_block(0, 20, 100)
+    s.P2.add_block(0, 20, -100)
+    s.SD1.acquire(0, 1000, wait=True)
+    s.SD2.acquire(0, 1000, wait=True)
+
+    sequence = pulse.mk_sequence([s])
+    sequence.n_rep = None
+    context.add_hw_schedule(sequence)
+    sequence.upload()
+    sequence.play()
+    data = sequence.get_measurement_results()
+    print(data)
+
+    return None
+
+def test2(iq_mode):
+    pulse = context.init_pulselib(n_gates=2, n_sensors=2, rf_sources=True)
+
+    s = pulse.mk_segment()
+
+    s.P1.add_block(0, 20, 100)
+    s.P2.add_block(0, 20, 100)
+
+    s.SD1.acquire(0, 1000, wait=True)
+    s.SD2.acquire(0, 1000, wait=True)
+
+    sequence = pulse.mk_sequence([s])
+    sequence.n_rep = 4
+    context.add_hw_schedule(sequence)
+
+    sequence.upload()
+    sequence.play()
+    data = sequence.get_measurement_results(iq_mode=iq_mode)
+    print(data)
+
+    return None
+
+
+if __name__ == '__main__':
+    ds1 = test1()
+    ds2 = []
+    for iq_mode in ['Complex', 'I', 'Q', 'amplitude', 'phase', 'I+Q', 'amplitude+phase']:
+        ds2.append(test2(iq_mode))
diff --git a/pulse_lib/tests/acquire/test_measurement_param.py b/pulse_lib/tests/acquire/test_measurement_param.py
new file mode 100644
index 0000000000000000000000000000000000000000..286e1d25dcb5c7d5d8ae3408cde269a5abf2b418
--- /dev/null
+++ b/pulse_lib/tests/acquire/test_measurement_param.py
@@ -0,0 +1,85 @@
+
+from pulse_lib.tests.configurations.test_configuration import context
+
+#%%
+def test1():
+    pulse = context.init_pulselib(n_gates=2, n_sensors=2)
+
+    s = pulse.mk_segment()
+
+    s.P1.add_block(0, 20, 100)
+    s.P2.add_block(0, 20, -100)
+    s.SD1.acquire(0, 1000, wait=True)
+    s.SD2.acquire(0, 1000, wait=True)
+
+    sequence = pulse.mk_sequence([s])
+    sequence.n_rep = None
+    m_param = sequence.get_measurement_param()
+    context.add_hw_schedule(sequence)
+
+    return context.run('m_param1', sequence, m_param)
+
+def test2():
+    pulse = context.init_pulselib(n_gates=2, n_sensors=2)
+
+    s = pulse.mk_segment()
+
+    # 2 acquisitions on channel 2
+    s.P1.add_block(0, 20, 100)
+
+    s.SD2.acquire(0, 1000, wait=True)
+    s.reset_time()
+    s.SD2.acquire(0, 1000, wait=True)
+
+    sequence = pulse.mk_sequence([s])
+    sequence.n_rep = 4
+    m_param = sequence.get_measurement_param()
+    context.add_hw_schedule(sequence)
+
+    return context.run('m_param2', sequence, m_param)
+
+def test3(iq_mode):
+    pulse = context.init_pulselib(n_gates=2, n_sensors=2, rf_sources=True)
+
+    s = pulse.mk_segment()
+
+    s.P1.add_block(0, 20, 100)
+    s.P2.add_block(0, 20, 100)
+
+    s.SD1.acquire(0, 1000, wait=True)
+    s.SD2.acquire(0, 1000, wait=True)
+
+    sequence = pulse.mk_sequence([s])
+    sequence.n_rep = 4
+    m_param = sequence.get_measurement_param(iq_mode=iq_mode)
+    context.add_hw_schedule(sequence)
+
+    return context.run('m_param3_'+iq_mode, sequence, m_param)
+
+def test4():
+    pulse = context.init_pulselib(n_gates=2, n_sensors=2)
+
+    s = pulse.mk_segment()
+
+    s.P1.add_block(0, 20, 100) #lp.linspace(-100, 100, 5, axis=0, name='amplitude', unit='mV'))
+    s.P2.add_block(0, 20, -100)
+    s.SD1.acquire(0, 1000, threshold=1.0, wait=True)
+    s.SD2.acquire(0, 1000, threshold=2.0, wait=True)
+
+    sequence = pulse.mk_sequence([s])
+    sequence.n_rep = 4
+    m_param = sequence.get_measurement_param()
+    context.add_hw_schedule(sequence)
+
+    return context.run('m_param2', sequence, m_param)
+
+#%%
+
+if __name__ == '__main__':
+    ds1 = test1()
+    ds2 = test2()
+    ds3 = []
+    for iq_mode in [#'Complex',
+                    'I', 'Q', 'amplitude', 'phase', 'I+Q', 'amplitude+phase']:
+        ds3.append(test3(iq_mode))
+    ds4 = test4()
diff --git a/pulse_lib/tests/segments/conditional_segments.py b/pulse_lib/tests/segments/conditional_segments.py
new file mode 100644
index 0000000000000000000000000000000000000000..6c4989d1e04c4ec4dc31cb1858fb6fe687476840
--- /dev/null
+++ b/pulse_lib/tests/segments/conditional_segments.py
@@ -0,0 +1,78 @@
+
+from pulse_lib.tests.configurations.test_configuration import context
+
+
+#%%
+from pulse_lib.segments.conditional_segment import conditional_segment
+from pulse_lib.segments.utility.measurement_ref import MeasurementRef
+
+def test1():
+    pulse = context.init_pulselib(n_gates=2, n_qubits=2, n_sensors=2)
+
+    t_measure = 500
+
+    s = pulse.mk_segment('seg1')
+    s1 = s
+
+    s.P1.add_block(10, 20, -10)
+    s.wait(30, reset_time=True)
+    s.SD1.acquire(0, t_measure, 'm1', threshold=0.0015, zero_on_high=True, wait=True)
+    s.wait(300, reset_time=True)
+
+    s_true = pulse.mk_segment()
+    s_false = pulse.mk_segment()
+
+    s_false.q1.add_MW_pulse(10, 20, 80.0, 2.450e9)
+    s_false.wait(10, reset_time=True)
+
+    cond_seg1 = conditional_segment(MeasurementRef('m1'), [s_false, s_true], name='cond')
+
+    sequence = pulse.mk_sequence([s1, cond_seg1])
+    sequence.n_rep = 3
+    context.add_hw_schedule(sequence)
+
+    context.plot_awgs(sequence, ylim=(-0.100,0.100))
+
+    m_param = sequence.get_measurement_param()
+    return context.run('feedback', sequence, m_param)
+
+
+def test2():
+    pulse = context.init_pulselib(n_gates=2, n_qubits=2, n_sensors=2)
+
+    t_measure = 500
+
+    s = pulse.mk_segment('seg1')
+    s1 = s
+
+    s.P1.add_block(10, 20, -10)
+    s.wait(30, reset_time=True)
+    s.SD1.acquire(0, t_measure, 'm0', threshold=0.0025, zero_on_high=True, wait=True)
+    s.wait(300, reset_time=True)
+    s.SD1.acquire(0, t_measure, 'm1', threshold=0.0025, zero_on_high=True, wait=True)
+    s.wait(300, reset_time=True)
+
+    s_true = pulse.mk_segment()
+    s_false = pulse.mk_segment()
+
+    s_false.q1.add_MW_pulse(10, 20, 80.0, 2.450e9)
+    s_false.wait(10, reset_time=True)
+
+    cond_seg1 = conditional_segment(MeasurementRef('m0'), [s_false, s_true], name='cond')
+
+    sequence = pulse.mk_sequence([s1, cond_seg1])
+    sequence.n_rep = 3
+    context.add_hw_schedule(sequence)
+
+    context.plot_awgs(sequence, ylim=(-0.100,0.100))
+
+    m_param = sequence.get_measurement_param()
+    return context.run('feedback', sequence, m_param)
+
+
+#%%
+if __name__ == '__main__':
+    context.init_coretools()
+#    ds1 = test1()
+    ds2 = test2()
+
diff --git a/pulse_lib/tests/specials/test_qblox_2D_video_mode.py b/pulse_lib/tests/specials/test_qblox_2D_video_mode.py
new file mode 100644
index 0000000000000000000000000000000000000000..1c8097316ecb1c883d0255a18d42251a22afdca6
--- /dev/null
+++ b/pulse_lib/tests/specials/test_qblox_2D_video_mode.py
@@ -0,0 +1,43 @@
+
+from pulse_lib.tests.configurations.test_configuration import context
+
+#%%
+from core_tools.GUI.keysight_videomaps.data_getter.scan_generator_Qblox import (
+        construct_1D_scan_fast, construct_2D_scan_fast)
+
+
+def test1D():
+    pulse = context.init_pulselib(n_gates=4, n_sensors=2, n_markers=1)
+    pulse.add_channel_delay('SD1', 165)
+    m_param = construct_1D_scan_fast(
+            'P1', 100, 200,
+            10_000, False, pulse,
+            channels=['SD1'],
+            enabled_markers=['M1'],
+            acquisition_delay_ns=500,
+            line_margin=1)
+
+    return m_param, m_param()
+
+
+def test2D():
+    pulse = context.init_pulselib(n_gates=4, n_sensors=2, n_qubits=2, n_markers=1,
+                                  rf_sources=True, virtual_gates=True)
+    pulse.add_channel_delay('SD2', 168)
+    m_param = construct_2D_scan_fast(
+            'vP1', 40/0.145, 200,
+            'vP2', 40/0.145, 200,
+            12_000, True, pulse,
+            channels=['SD1', 'SD2'],
+#            enabled_markers=['M1'],
+            acquisition_delay_ns=500,
+            line_margin=1)
+
+    return m_param, m_param()
+
+
+#%%
+if __name__ == '__main__':
+    param, data = test1D()
+    param, data = test2D()
+
diff --git a/pulse_lib/tests/unit/test_looping_functions.py b/pulse_lib/tests/unit/test_looping_functions.py
new file mode 100644
index 0000000000000000000000000000000000000000..600ebfff6fd541b29a9ebe98ce2e57930742a1bb
--- /dev/null
+++ b/pulse_lib/tests/unit/test_looping_functions.py
@@ -0,0 +1,38 @@
+import numpy as np
+
+def test_rounding():
+#    max_shuttle_rounds = 6000
+#    n_steps = 20
+#
+#    # option 1: relying on rounding and padding at the end to get total time.
+#    shuttles = np.round(np.geomspace(1, max_shuttle_rounds, n_steps))
+#
+#    # optino 2: use nice series of values matching 1 ns wqit times
+#    shuttles = np.array([1, 2, 3, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 3000, 3600, 4500, 6000])
+
+    max_shuttle_rounds = 20
+    shuttle_step = 1
+    shuttles = np.arange(1, max_shuttle_rounds+1, shuttle_step)
+
+    ramp_time = 5 # ns
+    total_wait = 200
+
+    wait_per_dot = ((total_wait-(2*ramp_time*shuttles))/2*shuttles)
+#    wait_per_dot = total_wait/(2*shuttles)-ramp_time
+#    wait_per_dot = total_wait/shuttles
+    wait_per_dot_int = np.floor(wait_per_dot)
+    padding = total_wait - wait_per_dot_int*shuttles
+
+    # NOTE: total time includes the ramp time. Total time is not constant!
+    total_time = (2*ramp_time+2*wait_per_dot_int)*shuttles + padding
+
+    with np.printoptions(formatter={'float':lambda x:f'{x:6.1f}'}):
+        print(shuttles)
+        print(wait_per_dot)
+        print(wait_per_dot_int)
+        print(padding)
+        print(total_time)
+
+
+if __name__ == '__main__':
+    test_rounding()