Skip to content

Commit

Permalink
Avoid races in start_playing, use improved time accuracy to improve c…
Browse files Browse the repository at this point in the history
…amera test reliability.
  • Loading branch information
cmeyer committed Dec 30, 2024
1 parent cfaae2d commit 554f688
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 42 deletions.
64 changes: 28 additions & 36 deletions nion/instrumentation/test/CameraControl_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ def test_change_to_profile_with_different_size_during_acquisition_should_produce
frame_parameters_1.binning = 1
hardware_source.set_frame_parameters(1, frame_parameters_1)
hardware_source.set_selected_profile_index(0)
hardware_source.start_playing()
hardware_source.start_playing(sync_timeout=3.0)
try:
self.assertEqual(hardware_source.get_next_xdatas_to_start()[0].data.shape, hardware_source.get_expected_dimensions(2))
time.sleep(self.exposure * 1.1)
Expand All @@ -306,7 +306,7 @@ def test_changing_frame_parameters_during_view_does_not_affect_current_acquisiti
frame_parameters = hardware_source.get_frame_parameters(profile_index)
frame_parameters.binning = 4
frame_time = frame_parameters.exposure_ms / 1000.0
hardware_source.start_playing()
hardware_source.start_playing(sync_timeout=3.0)
try:
# the time taken to start playing is unpredictable,
# so first make sure the camera is playing.
Expand Down Expand Up @@ -336,7 +336,7 @@ def test_capturing_during_view_captures_new_data_items(self):
document_model = test_context.document_model
hardware_source = test_context.camera_hardware_source
state_controller = self.__create_state_controller(test_context)
hardware_source.start_playing()
hardware_source.start_playing(sync_timeout=3.0)
try:
hardware_source.get_next_xdatas_to_finish(5)
document_controller.periodic()
Expand All @@ -354,7 +354,7 @@ def test_capturing_during_view_captures_eels_2d(self):
document_model = test_context.document_model
hardware_source = test_context.camera_hardware_source
state_controller = self.__create_state_controller(test_context)
hardware_source.start_playing()
hardware_source.start_playing(sync_timeout=3.0)
try:
hardware_source.get_next_xdatas_to_finish(5)
document_controller.periodic()
Expand All @@ -374,7 +374,7 @@ def test_capturing_during_view_captures_eels_1d(self):
document_model = test_context.document_model
hardware_source = test_context.camera_hardware_source
state_controller = self.__create_state_controller(test_context)
hardware_source.start_playing()
hardware_source.start_playing(sync_timeout=3.0)
try:
hardware_source.get_next_xdatas_to_finish(5)
document_controller.periodic()
Expand All @@ -395,7 +395,7 @@ def test_capturing_during_view_captures_session(self):
hardware_source = test_context.camera_hardware_source
state_controller = self.__create_state_controller(test_context)
ApplicationData.get_session_metadata_model().microscopist = "Ned Flanders"
hardware_source.start_playing()
hardware_source.start_playing(sync_timeout=3.0)
try:
hardware_source.get_next_xdatas_to_finish(5)
document_controller.periodic()
Expand All @@ -416,7 +416,7 @@ def test_ability_to_start_playing_with_custom_parameters(self):
frame_parameters_0 = hardware_source.get_frame_parameters(0)
frame_parameters_0.binning = 4
hardware_source.set_current_frame_parameters(frame_parameters_0)
hardware_source.start_playing()
hardware_source.start_playing(sync_timeout=3.0)
try:
hardware_source.get_next_xdatas_to_finish(10)
finally:
Expand Down Expand Up @@ -483,7 +483,7 @@ def test_first_view_uses_correct_mode(self):
state_controller = self.__create_state_controller(test_context)
state_controller.handle_change_profile("Snap")
state_controller.handle_binning_changed("4")
hardware_source.start_playing()
hardware_source.start_playing(sync_timeout=3.0)
try:
time.sleep(self.exposure * 0.5)
hardware_source.get_next_xdatas_to_finish() # view again
Expand All @@ -505,11 +505,12 @@ def test_first_view_uses_correct_exposure(self):
state_controller.handle_change_profile("Snap")
state_controller.handle_binning_changed("4")
state_controller.handle_exposure_changed(long_exposure)
start = time.time()
hardware_source.start_playing()
start = time.perf_counter()
hardware_source.start_playing(sync_timeout=3.0)
try:
hardware_source.get_next_xdatas_to_finish() # view again
elapsed = time.time() - start
time.sleep(0.001) # try to avoid Windows timer low precision issues
elapsed = time.perf_counter() - start
document_controller.periodic()
self.assertEqual(document_model.data_items[0].data_shape, hardware_source.get_expected_dimensions(4))
self.assertTrue(elapsed > long_exposure)
Expand All @@ -525,23 +526,19 @@ def test_view_followed_by_frame_uses_correct_exposure(self):
state_controller.handle_binning_changed("4")
state_controller.handle_exposure_changed(long_exposure)
state_controller.handle_change_profile("Run")
hardware_source.start_playing()
hardware_source.start_playing(sync_timeout=3.0)
try:
time.sleep(self.exposure * 0.5)
data_and_metadata = hardware_source.get_next_xdatas_to_finish()[0] # view again
self.assertEqual(data_and_metadata.data_shape, hardware_source.get_expected_dimensions(2))
finally:
hardware_source.stop_playing()
start_time = time.time()
while hardware_source.is_playing:
time.sleep(self.exposure)
self.assertTrue(time.time() - start_time < TIMEOUT)
hardware_source.stop_playing(sync_timeout=3.0)
state_controller.handle_change_profile("Snap")
hardware_source.start_playing()
hardware_source.start_playing(sync_timeout=3.0)
try:
start = time.time()
start = time.perf_counter()
data_and_metadata = hardware_source.get_next_xdatas_to_finish()[0] # frame now
elapsed = time.time() - start
elapsed = time.perf_counter() - start
finally:
hardware_source.abort_playing()
self.assertEqual(data_and_metadata.data_shape, hardware_source.get_expected_dimensions(4))
Expand All @@ -564,7 +561,7 @@ def raise_exception():
raise Exception("Error during acquisition")
hardware_source._test_acquire_hook = raise_exception
hardware_source._test_acquire_exception = lambda *args: None
hardware_source.start_playing()
hardware_source.start_playing(sync_timeout=3.0)
try:
hardware_source.get_next_xdatas_to_finish()
document_controller.periodic()
Expand Down Expand Up @@ -613,7 +610,7 @@ def processed_data_item_changed():
data_items[1] = state_controller.processed_data_item_reference.data_item
data_item_reference_changed_listener = state_controller.data_item_reference.data_item_reference_changed_event.listen(display_data_item_changed)
processed_data_item_reference_changed_listener = state_controller.processed_data_item_reference.data_item_reference_changed_event.listen(processed_data_item_changed)
hardware_source.start_playing()
hardware_source.start_playing(sync_timeout=3.0)
try:
for _ in range(4):
hardware_source.get_next_xdatas_to_finish()
Expand All @@ -640,23 +637,18 @@ def processed_data_item_changed():
data_item_reference_changed_listener = state_controller.data_item_reference.data_item_reference_changed_event.listen(display_data_item_changed)
processed_data_item_reference_changed_listener = state_controller.processed_data_item_reference.data_item_reference_changed_event.listen(processed_data_item_changed)
# first acquisition
hardware_source.start_playing()
hardware_source.start_playing(sync_timeout=3.0)
try:
for _ in range(4):
hardware_source.get_next_xdatas_to_finish()
document_controller.periodic()
finally:
hardware_source.abort_playing()
hardware_source.abort_playing(sync_timeout=3.0)
document_model.recompute_all()
# make sure really stopped
start_time = time.time()
while hardware_source.is_playing:
time.sleep(self.exposure)
self.assertTrue(time.time() - start_time < TIMEOUT)
self.assertEqual(len(document_model.data_items), 2)
# second acquisition
first_data_items = copy.copy(data_items)
hardware_source.start_playing()
hardware_source.start_playing(sync_timeout=3.0)
try:
for _ in range(4):
hardware_source.get_next_xdatas_to_finish()
Expand Down Expand Up @@ -767,7 +759,7 @@ def test_consecutive_frames_have_unique_data(self):
self.source_image = numpy.random.randn(1024, 1024).astype(numpy.float32)
with self._test_context() as test_context:
hardware_source = test_context.camera_hardware_source
hardware_source.start_playing()
hardware_source.start_playing(sync_timeout=3.0)
try:
data = hardware_source.get_next_xdatas_to_finish()[0].data
last_hash = zlib.crc32(data)
Expand All @@ -788,7 +780,7 @@ def test_integrating_frames_updates_frame_count_by_integration_count(self):
frame_parameters = hardware_source.get_frame_parameters(0)
frame_parameters.integration_count = 4
hardware_source.set_current_frame_parameters(frame_parameters)
hardware_source.start_playing()
hardware_source.start_playing(sync_timeout=3.0)
try:
frame0_integration_count = hardware_source.get_next_xdatas_to_finish()[0].metadata["hardware_source"]["integration_count"]
frame1_integration_count = hardware_source.get_next_xdatas_to_finish()[0].metadata["hardware_source"]["integration_count"]
Expand Down Expand Up @@ -1073,7 +1065,7 @@ def test_acquisition_state_updates_during_acquisition(self):
hardware_source = test_context.camera_hardware_source
state_controller = self.__create_state_controller(test_context)
self.assertEqual(state_controller.acquisition_state_model.value, "stopped")
hardware_source.start_playing()
hardware_source.start_playing(sync_timeout=3.0)
try:
hardware_source.get_next_xdatas_to_finish(5)
document_controller.periodic()
Expand All @@ -1092,7 +1084,7 @@ def raise_exception():
hardware_source._test_start_hook = raise_exception
hardware_source._test_acquire_exception = lambda *args: None
state_controller = self.__create_state_controller(test_context)
hardware_source.start_playing()
hardware_source.start_playing(sync_timeout=3.0)
try:
hardware_source.get_next_xdatas_to_finish(5)
document_controller.periodic()
Expand All @@ -1110,7 +1102,7 @@ def raise_exception():
hardware_source._test_acquire_hook = raise_exception
hardware_source._test_acquire_exception = lambda *args: None
state_controller = self.__create_state_controller(test_context)
hardware_source.start_playing()
hardware_source.start_playing(sync_timeout=3.0)
try:
hardware_source.get_next_xdatas_to_finish(5)
document_controller.periodic()
Expand Down Expand Up @@ -1514,7 +1506,7 @@ def test_eels_summed_controller_is_recognized_when_dropping_data_into_display_pa
document_controller = test_context.document_controller
document_model = test_context.document_model
state_controller = self.__create_state_controller(test_context)
hardware_source.start_playing()
hardware_source.start_playing(sync_timeout=3.0)
try:
hardware_source.get_next_xdatas_to_finish(5)
state_controller.use_processed_data = True
Expand Down
7 changes: 5 additions & 2 deletions nion/instrumentation/test/HardwareSource_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1260,8 +1260,11 @@ def test_data_item_created_during_acquisition_is_write_delayed_during_and_not_af
document_model = simple_test_context.document_model
hardware_source.start_playing(sync_timeout=3.0)
try:
time.sleep(0.02)
document_controller.periodic()
start_time = time.time()
while len(document_model.data_items) == 0:
time.sleep(0.001)
document_controller.periodic()
self.assertTrue(time.time() - start_time < 3.0)
self.assertEqual(1, len(document_model.data_items))
self.assertTrue(document_model.data_items[0].is_write_delayed)
finally:
Expand Down
6 changes: 2 additions & 4 deletions nion/instrumentation/test/MultiAcquire_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,8 @@ def test_acquire_multi_eels_spectrum_works_and_finishes_in_time(self):
with self.__test_context(is_eels=True) as test_context:
total_acquisition_time = 0.0
for parms in parameters:
# the simulator cant go super fast, so make sure we give it enough time
total_acquisition_time += parms['frames']*max(parms['exposure_ms'], 100)/1000
# add some extra overhead time
total_acquisition_time += 0.30
# give the simulator enough time + overhead
total_acquisition_time += parms['frames']*max(parms['exposure_ms'], 100)/1000 + 0.50
total_acquisition_time += settings['x_shift_delay']*2
total_acquisition_time += settings['x_shift_delay']*2
total_acquisition_time += settings['blanker_delay']*2 if settings['auto_dark_subtract'] else 0
Expand Down

0 comments on commit 554f688

Please sign in to comment.