def test_get_pos_first_tile(self): """Test that the position of the first tile is calculated correctly for a varying number of fields.""" res_x, res_y = self.multibeam.resolution.value # single field size px_size_x, px_size_y = self.multibeam.pixelSize.value # Loop over different ROA sizes by varying the number of fields in x and y. for x_fields, y_fields in zip((1, 2, 40, 34, 5), (1, 22, 43, 104, 25)): # The coordinates of the ROA in meters. xmin, ymin, xmax, ymax = (0, 0, res_x * px_size_x * x_fields, res_y * px_size_y * y_fields) coordinates = (xmin, ymin, xmax, ymax) # in m # Create an ROA with the coordinates of the field. roa_name = time.strftime("test_megafield_id-%Y-%m-%d-%H-%M-%S") roa = fastem.FastEMROA(roa_name, coordinates, None, None, self.asm, self.multibeam, self.descanner, self.mppc) task = fastem.AcquisitionTask(self.scanner, self.multibeam, self.descanner, self.mppc, self.stage, self.ccd, self.beamshift, self.lens, roa, path=None, pre_calibrations=None, future=None) pos_first_tile_actual = task.get_pos_first_tile() # The position of the first tile is expected to be to the center position of the top left corner tile # of the ROA. pos_first_tile_expected = (xmin + res_x / 2 * px_size_x, ymax - res_y / 2 * px_size_y) self.assertEqual(pos_first_tile_actual, pos_first_tile_expected)
def test_pre_calibrate(self): """ Test the ASM settings are unchanged after running the pre-calibrations, except the descanner scan offset. """ try: import fastem_calibrations except ImportError as err: raise unittest.SkipTest(f"Skipping 'test_pre_calibrate', correct libraries to perform this test are not available.\n" f"Got the error: {err}") res_x, res_y = self.multibeam.resolution.value # single field size px_size_x, px_size_y = self.multibeam.pixelSize.value x_fields = 5 y_fields = 8 # The coordinates of the ROA in meters. xmin, ymin, xmax, ymax = (0, 0, res_x * px_size_x * x_fields, res_y * px_size_y * y_fields) coordinates = (xmin, ymin, xmax, ymax) # in m # Create an ROA with the coordinates of the field. roa_name = time.strftime("test_megafield_id-%Y-%m-%d-%H-%M-%S") roa = fastem.FastEMROA(roa_name, coordinates, None, None, self.asm, self.multibeam, self.descanner, self.mppc) task = fastem.AcquisitionTask(self.scanner, self.multibeam, self.descanner, self.mppc, self.stage, self.ccd, self.beamshift, self.lens, roa, path=None, pre_calibrations=None, future=None) self.descanner.updateMetadata({model.MD_SCAN_GAIN: (5000, 5000)}) # Set the _pos_first_tile, which would normally be set in the run function. task._pos_first_tile = task.get_pos_first_tile() asm_config_orig = configure_hw.get_config_asm(self.multibeam, self.descanner, self.mppc) pre_calibrations = [Calibrations.OPTICAL_AUTOFOCUS, Calibrations.IMAGE_TRANSLATION_PREALIGN] task.pre_calibrate(pre_calibrations=pre_calibrations) asm_config_current = configure_hw.get_config_asm(self.multibeam, self.descanner, self.mppc) # Verify that all settings, except the descanner scan offset, stay the same after running the pre-calibrations. for component, settings in asm_config_current.items(): for va, value in settings.items(): if va == 'scanOffset' and component == 'descanner': # image translation pre-alignment changes the descanner offset, therefore it has changed. continue self.assertEqual(asm_config_orig[component][va], value)
def test_stage_pos_outside_roa(self): """ The pre-calibrations need to run outside the ROA. Test that get_abs_stage_movement returns the correct value for a field index of (-1, -1) and that that value is outside the ROA. """ res_x, res_y = self.multibeam.resolution.value # single field size px_size_x, px_size_y = self.multibeam.pixelSize.value x_fields, y_fields = (3, 4) field_size_x = res_x * px_size_x field_size_y = res_y * px_size_y # The coordinates of the ROA in meters. xmin, ymin = (0, 0) xmax, ymax = (field_size_x * x_fields, field_size_y * y_fields) coordinates = (xmin, ymin, xmax, ymax) # in m # Create an ROA with the coordinates of the field. roa_name = time.strftime("test_megafield_id-%Y-%m-%d-%H-%M-%S") roa = fastem.FastEMROA(roa_name, coordinates, None, None, self.asm, self.multibeam, self.descanner, self.mppc) task = fastem.AcquisitionTask(self.scanner, self.multibeam, self.descanner, self.mppc, self.stage, self.ccd, self.beamshift, self.lens, roa, path=None, pre_calibrations=None, future=None) # Set the _pos_first_tile, which would normally be set in the run function. task._pos_first_tile = task.get_pos_first_tile() # Verify that for pre-calibrations compared to the top left corner of the ROA, the stage # position is located half a field to the top left (outside the ROA). task.field_idx = (-1, -1) # (-1, -1) is the index where the pre-calibrations are performed # In the role='stage' coordinate system the x-axis points to the right and y-axis to the top. expected_position = (xmin - res_x / 2 * px_size_x, ymax + res_x / 2 * px_size_y) # [m] actual_position = task.get_abs_stage_movement() # [m] numpy.testing.assert_allclose(actual_position, expected_position) # Verify that the position where the pre-calibration is performed, does not lie inside the ROA coordinates. self.assertFalse(is_point_in_rect(actual_position, coordinates))
def test_get_abs_stage_movement_overlap(self): """ Test the correct stage positions are returned for the corner fields of ROAs when there is an overlap in between fields. """ res_x, res_y = self.multibeam.resolution.value # single field size px_size_x, px_size_y = self.multibeam.pixelSize.value x_fields, y_fields = (3, 4) field_size_x = res_x * px_size_x field_size_y = res_y * px_size_y for overlap in (0, 0.0625, 0.2, 0.5, 0.7): # The coordinates of the ROA in meters. xmin, ymin = (0, 0) # The max field size is the number of fields multiplied with the field size including overlap, plus # the extra overlap added to the end. xmax, ymax = (field_size_x * x_fields * (1 - overlap) + field_size_x * overlap, field_size_y * y_fields * (1 - overlap) + field_size_y * overlap) coordinates = (xmin, ymin, xmax, ymax) # in m # Create an ROA with the coordinates of the field. roa_name = time.strftime("test_megafield_id-%Y-%m-%d-%H-%M-%S") roa = fastem.FastEMROA(roa_name, coordinates, None, None, self.asm, self.multibeam, self.descanner, self.mppc, overlap) task = fastem.AcquisitionTask(self.scanner, self.multibeam, self.descanner, self.mppc, self.stage, self.ccd, self.beamshift, self.lens, roa, path=None, pre_calibrations=None, future=None) # Set the _pos_first_tile, which would normally be set in the run function. task._pos_first_tile = task.get_pos_first_tile() # Verify that compared to the top left corner of the ROA, the stage # position is located half a field to the bottom right. task.field_idx = (0, 0) # (0, 0) is the index of the first field # In the role='stage' coordinate system the x-axis points to the right and y-axis to the top. expected_position = (xmin + res_x / 2 * px_size_x, ymax - res_x / 2 * px_size_y) # [m] actual_position = task.get_abs_stage_movement() # [m] numpy.testing.assert_allclose(actual_position, expected_position) # Verify that compared to the bottom right corner of the ROA, the stage # position is located half a field to the top left. task.field_idx = (x_fields - 1, y_fields - 1) # index of the last field # In the role='stage' coordinate system the x-axis points to the right and y-axis to the top. expected_position = (xmax - res_x / 2 * px_size_x, ymin + res_x / 2 * px_size_y) # [m] actual_position = task.get_abs_stage_movement() # [m] numpy.testing.assert_allclose(actual_position, expected_position) # Verify that compared to the top right corner of the ROA, the stage # position is located half a field to the bottom left. task.field_idx = (x_fields - 1, 0) # index of the last field in x and first field in y expected_position = (xmax - res_x / 2 * px_size_x, ymax - res_x / 2 * px_size_y) # [m] actual_position = task.get_abs_stage_movement() # [m] numpy.testing.assert_allclose(actual_position, expected_position) # Verify that compared to the bottom left corner of the ROA, the stage # position is located half a field to the top right. task.field_idx = (0, y_fields - 1) # index of the first field in x and the last field in y # In the role='stage' coordinate system the x-axis points to the right and y-axis to the top. expected_position = (xmin + res_x / 2 * px_size_x, ymin + res_x / 2 * px_size_y) # [m] actual_position = task.get_abs_stage_movement() # [m] numpy.testing.assert_allclose(actual_position, expected_position)
def test_get_abs_stage_movement(self): """ Test the correct stage positions are returned for the corner fields of ROAs consisting of a varying number of single fields. """ res_x, res_y = self.multibeam.resolution.value # single field size px_size_x, px_size_y = self.multibeam.pixelSize.value # Loop over different ROA sizes by varying the number of fields in x and y. for x_fields, y_fields in zip((1, 2, 40, 34, 5), (1, 22, 43, 104, 25)): # The coordinates of the ROA in meters. xmin, ymin, xmax, ymax = (0, 0, res_x * px_size_x * x_fields, res_y * px_size_y * y_fields) coordinates = (xmin, ymin, xmax, ymax) # in m # Create an ROA with the coordinates of the field. roa_name = time.strftime("test_megafield_id-%Y-%m-%d-%H-%M-%S") roa = fastem.FastEMROA(roa_name, coordinates, None, None, self.asm, self.multibeam, self.descanner, self.mppc) task = fastem.AcquisitionTask(self.scanner, self.multibeam, self.descanner, self.mppc, self.stage, self.ccd, self.beamshift, self.lens, roa, path=None, pre_calibrations=None, future=None) # Set the _pos_first_tile, which would normally be set in the run function. task._pos_first_tile = task.get_pos_first_tile() # Verify that compared to the top left corner of the ROA, the stage # position is located half a field to the bottom right. task.field_idx = (0, 0) # (0, 0) is the index of the first field # In the role='stage' coordinate system the x-axis points to the right and y-axis to the top. expected_position = (xmin + res_x / 2 * px_size_x, ymax - res_x / 2 * px_size_y) # [m] actual_position = task.get_abs_stage_movement() # [m] actual_position_first_tile = task.get_pos_first_tile() # [m] numpy.testing.assert_allclose(actual_position, expected_position) numpy.testing.assert_allclose(actual_position, actual_position_first_tile) # Verify that compared to the bottom right corner of the ROA, the stage # position is located half a field to the top left. task.field_idx = (x_fields - 1, y_fields - 1) # index of the last field # In the role='stage' coordinate system the x-axis points to the right and y-axis to the top. expected_position = (xmax - res_x / 2 * px_size_x, ymin + res_x / 2 * px_size_y) # [m] actual_position = task.get_abs_stage_movement() # [m] numpy.testing.assert_allclose(actual_position, expected_position) # Verify that compared to the top right corner of the ROA, the stage # position is located half a field to the bottom left. task.field_idx = (x_fields - 1, 0) # index of the last field in x and first field in y expected_position = (xmax - res_x / 2 * px_size_x, ymax - res_x / 2 * px_size_y) # [m] actual_position = task.get_abs_stage_movement() # [m] numpy.testing.assert_allclose(actual_position, expected_position) # Verify that compared to the bottom left corner of the ROA, the stage # position is located half a field to the top right. task.field_idx = (0, y_fields - 1) # index of the first field in x and the last field in y # In the role='stage' coordinate system the x-axis points to the right and y-axis to the top. expected_position = (xmin + res_x / 2 * px_size_x, ymin + res_x / 2 * px_size_y) # [m] actual_position = task.get_abs_stage_movement() # [m] numpy.testing.assert_allclose(actual_position, expected_position)