def test_progress_ROA(self): """Check if some progress is reported between the field images acquired for the ROA (megafield).""" x_fields = 2 y_fields = 3 res_x, res_y = self.multibeam.resolution.value # single field size px_size_x, px_size_y = self.multibeam.pixelSize.value coordinates = (0, 0, res_x * px_size_x * x_fields, res_y * px_size_y * y_fields) # in m roc_2 = fastem.FastEMROC("roc_2", coordinates) roc_3 = fastem.FastEMROC("roc_3", coordinates) roa_name = time.strftime("test_megafield_id-%Y-%m-%d-%H-%M-%S") roa = fastem.FastEMROA(roa_name, coordinates, roc_2, roc_3, self.asm, self.multibeam, self.descanner, self.mppc) path_storage = os.path.join(datetime.today().strftime('%Y-%m-%d'), "test_project_progress") self.updates = 0 # updated in callback on_progress_update f = fastem.acquire(roa, path_storage, self.scanner, self.multibeam, self.descanner, self.mppc, self.stage, self.ccd, self.beamshift, self.lens) f.add_update_callback(self.on_progress_update) # callback executed every time f.set_progress is called f.add_done_callback(self.on_done) # callback executed when f.set_result is called (via bindFuture) data, e = f.result() self.assertIsNone(e) # check no exceptions were returned self.assertIsInstance(data[(0, 0)], model.DataArray) self.assertTrue(self.done) self.assertGreaterEqual(self.updates, 6) # at least one update per field
def test_coverage_ROA(self): """Acquire a megafield (ROA), which does not match an integer multiple of fields. Check that the acquired ROA exceeds the requested ROA.""" x_fields = 3 y_fields = 4 self.multibeam.resolution.value = (6400, 6400) # don't change res_x, res_y = self.multibeam.resolution.value # single field size px_size_x, px_size_y = self.multibeam.pixelSize.value # some extra pixels (< 1 field) to be added to the ROA x_margin, y_margin = (res_x / 10, res_y / 20) coordinates = (0, 0, res_x * px_size_x * x_fields + x_margin * px_size_x, res_y * px_size_y * y_fields + y_margin * px_size_y) # in m roc_2 = fastem.FastEMROC("roc_2", coordinates) roc_3 = fastem.FastEMROC("roc_3", coordinates) roa_name = time.strftime("test_megafield_id-%Y-%m-%d-%H-%M-%S") roa = fastem.FastEMROA(roa_name, coordinates, roc_2, roc_3, self.asm, self.multibeam, self.descanner, self.mppc) path_storage = os.path.join(datetime.today().strftime('%Y-%m-%d'), "test_project_field_indices") f = fastem.acquire(roa, path_storage, self.scanner, self.multibeam, self.descanner, self.mppc, self.stage, self.ccd, self.beamshift, self.lens) data, e = f.result() self.assertIsNone(e) # check no exceptions were returned # check data returned contains the correct number of field images # expect plus 1 field in x and y respectively self.assertEqual(len(data), (x_fields + 1) * (y_fields + 1)) self.assertIsInstance(data[(0, 0)], model.DataArray)
def test_acquire_ROA(self): """Acquire a small mega field image with ROA matching integer multiple of single field size.""" x_fields = 2 y_fields = 3 self.multibeam.resolution.value = (6400, 6400) # don't change res_x, res_y = self.multibeam.resolution.value # single field size px_size_x, px_size_y = self.multibeam.pixelSize.value # Note: Do not change those values; _calculate_field_indices handles floating point errors the same way # as an ROA that does not match an integer number of field indices by just adding an additional row or column # of field images. top = -0.002 # top corner coordinate of ROA in stage coordinates in meter left = +0.001 # left corner coordinate of ROA in stage coordinates in meter coordinates = (top, left, top + res_x * px_size_x * x_fields, left + res_y * px_size_y * y_fields) # in m roc = fastem.FastEMROC("roc_name", coordinates) roa_name = time.strftime("test_megafield_id-%Y-%m-%d-%H-%M-%S") roa = fastem.FastEMROA(roa_name, coordinates, roc, self.asm, self.multibeam, self.descanner, self.mppc) path_storage = os.path.join(datetime.today().strftime('%Y-%m-%d'), "test_project_megafield") f = fastem.acquire(roa, path_storage, self.scanner, self.multibeam, self.descanner, self.mppc, self.stage, self.ccd, self.beamshift, self.lens) data, e = f.result() self.assertIsNone(e) # check no exceptions were returned # check data returned contains the correct number of field images self.assertEqual(len(data), x_fields * y_fields) self.assertIsInstance(data[(0, 0)], model.DataArray)
def on_acquisition(self, evt): """ Start the acquisition (really) """ self._main_data_model.is_acquiring.value = True self.btn_acquire.Enable(False) self.btn_cancel.Enable(True) self.btn_cancel.Show() self.gauge_acq.Show() self._show_status_icons(None) self.gauge_acq.Range = self.roa_count self.gauge_acq.Value = 0 # Acquire ROAs for all projects fs = {} for p in self._tab_data_model.projects.value: ppath = os.path.join(self.path, p.name.value) # <acquisition date>/<project name> for roa in p.roas.value: f = fastem.acquire(roa, ppath, self._main_data_model.ebeam, self._main_data_model.multibeam, self._main_data_model.descanner, self._main_data_model.mppc, self._main_data_model.stage, self._main_data_model.ccd, self._main_data_model.beamshift, self._main_data_model.lens) t = roa.estimate_acquisition_time() fs[f] = t self.acq_future = model.ProgressiveBatchFuture(fs) self._fs_connector = ProgressiveFutureConnector(self.acq_future, self.gauge_acq, self.lbl_acqestimate) self.acq_future.add_done_callback(self.on_acquisition_done)
def test_stage_movement(self): """Test that the stage move corresponds to one field image (excluding over-scanned pixels).""" x_fields = 2 y_fields = 3 res_x, res_y = self.multibeam.resolution.value # single field size px_size_x, px_size_y = self.multibeam.pixelSize.value # FIXME: This test does not consider yet, that ROA coordinates need to be transformed into the # correct coordinate system. Replace role='stage' with role='stage-scan' when function available. # Note: Do not change those values; _calculate_field_indices handles floating point errors the same way # as an ROA that does not match an integer number of field indices by just adding an additional row or column # of field images. xmin = -0.002 # top corner coordinate of ROA in stage coordinates in meter ymin = +0.001 # left corner coordinate of ROA in stage coordinates in meter xmax = xmin + res_x * px_size_x * x_fields ymax = ymin + res_y * px_size_y * y_fields coordinates = (xmin, ymin, xmax, ymax) # in m roc_2 = fastem.FastEMROC("roc_2", coordinates) roc_3 = fastem.FastEMROC("roc_3", coordinates) roa_name = time.strftime("test_megafield_id-%Y-%m-%d-%H-%M-%S") roa = fastem.FastEMROA(roa_name, coordinates, roc_2, roc_3, self.asm, self.multibeam, self.descanner, self.mppc) path_storage = os.path.join(datetime.today().strftime('%Y-%m-%d'), "test_project_stage_move") f = fastem.acquire(roa, path_storage, self.scanner, self.multibeam, self.descanner, self.mppc, self.stage, self.ccd, self.beamshift, self.lens) data, e = f.result() self.assertIsNone(e) # check no exceptions were returned # total expected stage movement in x and y during the acquisition # half a field to start at center of first field image exp_move_x = res_x / 2. * px_size_x + res_x * px_size_x * (x_fields - 1) exp_move_y = res_y / 2. * px_size_y + res_y * px_size_y * (y_fields - 1) # FIXME Needs to be updated when role="stage" is replaced with role="stage-scan" # In role="stage" coordinate system: # Move in the positive x direction, because the second field should be right of the first. # Move in the negative y direction, because the second field should be below the first. exp_position = (xmin + exp_move_x, ymax - exp_move_y) # get the last stage position (it is the center of the last field) cur_position = (self.stage.position.value['x'], self.stage.position.value['y']) # check stage position is matching expected position (Note: stage accuracy is ~ TODO fix decimal accordingly) numpy.testing.assert_almost_equal(exp_position, cur_position, decimal=6)
def test_stage_movement(self): """Test that the stage move corresponds to one field image (excluding over-scanned pixels).""" x_fields = 2 y_fields = 3 res_x, res_y = self.multibeam.resolution.value # single field size px_size_x, px_size_y = self.multibeam.pixelSize.value # FIXME: It is not clear in which coordinate system the coordinates of the ROA are!!! # Note: the coordinates are in the stage coordinate system with role='stage' and not role='stage-scan'. # However, for fast em acquisitions we use stage-scan, which scans along the multiprobe axes. # FIXME: This test does not consider yet, that ROA coordinates need to be transformed into the # correct coordinate system. Replace role='stage' with role='stage-scan' when function available. # Note: Do not change those values; _calculate_field_indices handles floating point errors the same way # as an ROA that does not match an integer number of field indices by just adding an additional row or column # of field images. top = -0.002 # top corner coordinate of ROA in stage coordinates in meter left = +0.001 # left corner coordinate of ROA in stage coordinates in meter coordinates = (top, left, top + res_x * px_size_x * x_fields, left + res_y * px_size_y * y_fields) # in m roc = fastem.FastEMROC("roc_name", coordinates) roa_name = time.strftime("test_megafield_id-%Y-%m-%d-%H-%M-%S") roa = fastem.FastEMROA(roa_name, coordinates, roc, self.asm, self.multibeam, self.descanner, self.mppc) path_storage = os.path.join(datetime.today().strftime('%Y-%m-%d'), "test_project_stage_move") f = fastem.acquire(roa, path_storage, self.multibeam, self.descanner, self.mppc, self.stage) data, e = f.result() self.assertIsNone(e) # check no exceptions were returned # total expected stage movement in x and y during the acquisition # half a field to start at center of first field image exp_move_x = res_x / 2. * px_size_x + res_x * px_size_x * (x_fields - 1) exp_move_y = res_y / 2. * px_size_y + res_y * px_size_y * (y_fields - 1) # TODO these comments are true, when stage is replaced with stage-scan # Move in the negative x direction, because the second field should be right of the first. # Move in positive y direction, because the second field should be bottom of the first. exp_position = (top - exp_move_x, left + exp_move_y) # get the last stage position (it is the center of the last field) cur_position = (self.stage.position.value['x'], self.stage.position.value['y']) # check stage position is matching expected position (Note: stage accuracy is ~ TODO fix decimal accordingly) numpy.testing.assert_almost_equal(exp_position, cur_position, decimal=6)
def test_cancel_ROA(self): """Test if it is possible to cancel between field images acquired for one ROA.""" x_fields = 2 y_fields = 3 res_x, res_y = self.multibeam.resolution.value # single field size px_size_x, px_size_y = self.multibeam.pixelSize.value coordinates = (0, 0, res_x * px_size_x * x_fields, res_y * px_size_y * y_fields) # in m roc = fastem.FastEMROC("roc_name", coordinates) roa_name = time.strftime("test_megafield_id-%Y-%m-%d-%H-%M-%S") roa = fastem.FastEMROA(roa_name, coordinates, roc, self.asm, self.multibeam, self.descanner, self.mppc) path_storage = os.path.join(datetime.today().strftime('%Y-%m-%d'), "test_project_cancel") self.end = None # updated in callback on_progress_update self.updates = 0 # updated in callback on_progress_update self.done = False # updated in callback on_done f = fastem.acquire(roa, path_storage, self.scanner, self.multibeam, self.descanner, self.mppc, self.stage, self.ccd, self.beamshift, self.lens) f.add_update_callback( self.on_progress_update ) # callback executed every time f.set_progress is called f.add_done_callback( self.on_done ) # callback executed when f.set_result is called (via bindFuture) time.sleep(1) # make sure it's started self.assertTrue(f.running()) f.cancel() self.assertRaises( CancelledError, f.result, 1) # add timeout = 1s in case cancellation error was not raised self.assertGreaterEqual(self.updates, 3) # at least one update at cancellation self.assertLessEqual(self.end, time.time()) self.assertTrue(self.done) self.assertTrue(f.cancelled())