From c8a1dbaa176e893651981dbdac02a6b3946b5020 Mon Sep 17 00:00:00 2001 From: Patrick Cleeve Date: Fri, 29 Mar 2024 21:14:50 +1100 Subject: [PATCH 1/2] Add system fingerprinting and configuration based on microscope information --- fibsem/configuration.py | 94 +++++++++++++++++++++++++++++++++++++++++ fibsem/microscope.py | 13 +++--- 2 files changed, 101 insertions(+), 6 deletions(-) diff --git a/fibsem/configuration.py b/fibsem/configuration.py index 7969a072..bfb73e91 100644 --- a/fibsem/configuration.py +++ b/fibsem/configuration.py @@ -3,6 +3,100 @@ import os from fibsem.config import CONFIG_PATH, DEFAULT_CONFIGURATION_VALUES +# TODO: +# eucentric heights -> requires taking an image? +# reference rotation -> how to get this without having the user move to position? + +def system_fingerprint(ip_address: str = "192.168.0.1", manufactuer: str = "Thermo") -> dict: + """Automatically configure system based on microscope fingerprinting.""" + + # load default configuration + with open(os.path.join(CONFIG_PATH, "microscope-configuration.yaml"), "r") as f: + config = yaml.safe_load(f) + + if manufactuer != "Thermo": + raise ValueError("Only Thermo Fisher microscopes are currently supported for fingerprinting.") + + # ip, manufacturer + config["info"]["ip"] = ip_address # default ip (support pc -> microscope pc) + config["info"]["manufacturer"] = manufactuer # default manufacturer + + from fibsem.microscope import ThermoMicroscope + + microscope = ThermoMicroscope() + microscope.connect_to_microscope(config["info"]["ip"]) + + # get name of system + system_name = microscope.connection.service.system.name + serial_number = microscope.connection.service.system.serial_number + config["info"]["name"] = f"{system_name}-{serial_number}-configuration" + + # stage + # enabled, compustage, rotation, tilt + stage_enabled = microscope.connection.specimen.stage.is_installed + compustage_enabled = microscope.connection.specimen.stage.compustage.is_installed + config["stage"]["enabled"] = stage_enabled or compustage_enabled + config["stage"]["rotation"] = stage_enabled + config["stage"]["tilt"] = stage_enabled or compustage_enabled + + # rotation reference, rotation_180 + if compustage_enabled: # TODO: check if this is accurate + config["stage"]["rotation_reference"] = 0 + config["stage"]["rotation_180"] = 0 + + # otherwise? I think need to get this manually? + # TODO: get the user to move the stage to this position? + # tilt = 0, rotation = same as when loading? + + # eucentric height map, [electron, ion] (otherwise we need to take an image to get this?) + eucentric_height_map = { + "Aquilios": [7e-3, 16.5e-3], + "Helios": [4e-3, 16.5e-3], + "Artcis": [4e-3, 16.5e-3], + "Scios": [4e-3, 10.0e-3] + } + + # electron beam + config["electron"]["enabled"] = microscope.connection.beams.electron_beam.is_installed + config["electron"]["column_tilt"] = get_column_tilt(config["info"]["manufacturer"], "electron") + config["electron"]["eucentric_height"] = eucentric_height_map[system_name][0] + + # ion beam + # is_installed, column tilt, eucentric_height (req taking image), plasma, plasma gas + config["ion"]["enabled"] = microscope.connection.beams.ion_beam.is_installed + config["ion"]["column_tilt"] = get_column_tilt(config["info"]["manufacturer"], "ion") + config["ion"]["eucentric_height"] = eucentric_height_map[system_name][1] + + # plasma enabled + ion_plasma_enabled = False + ion_plasma_gas = "None" + if config["ion"]["enabled"]: + + # check if plasma enabled + ion_plasma_enabled = hasattr(microscope.connection.beams.ion_beam.source, "plasma_gas") + + if ion_plasma_enabled: + ion_plasma_gas = microscope.connection.beams.ion_beam.source.plasma_gas.value + + config["ion"]["plasma"] = ion_plasma_enabled + config["ion"]["plasma_gas"] = ion_plasma_gas + + # manipulator + config["manipulator"]["enabled"] = microscope.connection.specimen.manipulator.is_installed + config["manipulator"]["rotation"] = False # always? + config["maniuplator"]["tilt"] = False # always? + + # gis + gis_enabled = len(microscope.connection.list_all_gis_ports()) + multichem_enabled = len(microscope.connection.list_all_multichem_ports()) + sputter_coater_enabled = microscope.connection.specimen.sputter_coater.is_installed + + config["gis"]["enabled"] = gis_enabled + config["gis"]["multichem"] = multichem_enabled + config["gis"]["sputter_coater"] = sputter_coater_enabled + + + return config def get_column_tilt(manufacturer: str, beam: str) -> int: diff --git a/fibsem/microscope.py b/fibsem/microscope.py index 61055768..7bfadf9a 100644 --- a/fibsem/microscope.py +++ b/fibsem/microscope.py @@ -808,12 +808,13 @@ def connect_to_microscope(self, ip_address: str, port: int = 7520) -> None: logging.info(f"Microscope client connected to [{ip_address}:{port}]") # system information - self.system.info.model = self.connection.service.system.name - self.system.info.serial_number = self.connection.service.system.serial_number - self.system.info.hardware_version = self.connection.service.system.version - self.system.info.software_version = self.connection.service.autoscript.client.version - info = self.system.info - logging.info(f"Microscope client connected to model {info.model} with serial number {info.serial_number} and software version {info.software_version}.") + if self.system is not None: + self.system.info.model = self.connection.service.system.name + self.system.info.serial_number = self.connection.service.system.serial_number + self.system.info.hardware_version = self.connection.service.system.version + self.system.info.software_version = self.connection.service.autoscript.client.version + info = self.system.info + logging.info(f"Microscope client connected to model {info.model} with serial number {info.serial_number} and software version {info.software_version}.") # autoscript information logging.info(f"Autoscript Client: {self.connection.service.autoscript.client.version}") From 701dcd13b2bb8deae3ceb200e92fc644051393d3 Mon Sep 17 00:00:00 2001 From: Patrick Cleeve <30920819+GenevieveBuckley@users.noreply.github.com> Date: Thu, 4 Apr 2024 15:10:14 +1100 Subject: [PATCH 2/2] hw test, gfib --- fibsem/configuration.py | 62 +++++++++++++++++++++++++++++++---------- fibsem/microscope.py | 8 ++++-- 2 files changed, 53 insertions(+), 17 deletions(-) diff --git a/fibsem/configuration.py b/fibsem/configuration.py index bfb73e91..d83a1d95 100644 --- a/fibsem/configuration.py +++ b/fibsem/configuration.py @@ -22,6 +22,7 @@ def system_fingerprint(ip_address: str = "192.168.0.1", manufactuer: str = "Ther config["info"]["manufacturer"] = manufactuer # default manufacturer from fibsem.microscope import ThermoMicroscope + from fibsem.structures import SystemSettings, BeamSystemSettings, StageSystemSettings, FibsemDetectorSettings microscope = ThermoMicroscope() microscope.connect_to_microscope(config["info"]["ip"]) @@ -34,9 +35,9 @@ def system_fingerprint(ip_address: str = "192.168.0.1", manufactuer: str = "Ther # stage # enabled, compustage, rotation, tilt stage_enabled = microscope.connection.specimen.stage.is_installed - compustage_enabled = microscope.connection.specimen.stage.compustage.is_installed + compustage_enabled = microscope.connection.specimen.compustage.is_installed config["stage"]["enabled"] = stage_enabled or compustage_enabled - config["stage"]["rotation"] = stage_enabled + config["stage"]["rotation"] = stage_enabled and not compustage_enabled config["stage"]["tilt"] = stage_enabled or compustage_enabled # rotation reference, rotation_180 @@ -56,27 +57,36 @@ def system_fingerprint(ip_address: str = "192.168.0.1", manufactuer: str = "Ther "Scios": [4e-3, 10.0e-3] } + # check if any key in system_name + for model in eucentric_height_map: + if model in system_name: + system_model = model + # electron beam config["electron"]["enabled"] = microscope.connection.beams.electron_beam.is_installed config["electron"]["column_tilt"] = get_column_tilt(config["info"]["manufacturer"], "electron") - config["electron"]["eucentric_height"] = eucentric_height_map[system_name][0] + config["electron"]["eucentric_height"] = eucentric_height_map[system_model][0] # ion beam # is_installed, column tilt, eucentric_height (req taking image), plasma, plasma gas config["ion"]["enabled"] = microscope.connection.beams.ion_beam.is_installed config["ion"]["column_tilt"] = get_column_tilt(config["info"]["manufacturer"], "ion") - config["ion"]["eucentric_height"] = eucentric_height_map[system_name][1] + config["ion"]["eucentric_height"] = eucentric_height_map[system_model][1] # plasma enabled ion_plasma_enabled = False - ion_plasma_gas = "None" + if config["ion"]["enabled"]: - - # check if plasma enabled - ion_plasma_enabled = hasattr(microscope.connection.beams.ion_beam.source, "plasma_gas") - - if ion_plasma_enabled: + + try: + # throws an ion_plasma_gas = microscope.connection.beams.ion_beam.source.plasma_gas.value + ion_plasma_enabled = True + print(f"Ion Plasma Available, Plasma Gas: {ion_plasma_gas}") + except Exception as e: + print(f"Exception: {e}") + ion_plasma_gas = "None" + ion_plasma_enabled = False config["ion"]["plasma"] = ion_plasma_enabled config["ion"]["plasma_gas"] = ion_plasma_gas @@ -84,17 +94,39 @@ def system_fingerprint(ip_address: str = "192.168.0.1", manufactuer: str = "Ther # manipulator config["manipulator"]["enabled"] = microscope.connection.specimen.manipulator.is_installed config["manipulator"]["rotation"] = False # always? - config["maniuplator"]["tilt"] = False # always? + config["manipulator"]["tilt"] = False # always? # gis - gis_enabled = len(microscope.connection.list_all_gis_ports()) - multichem_enabled = len(microscope.connection.list_all_multichem_ports()) + gis_enabled = len(microscope.connection.gas.list_all_gis_ports()) + multichem_enabled = len(microscope.connection.gas.list_all_multichem_ports()) sputter_coater_enabled = microscope.connection.specimen.sputter_coater.is_installed - config["gis"]["enabled"] = gis_enabled - config["gis"]["multichem"] = multichem_enabled + config["gis"]["enabled"] = bool(gis_enabled) + config["gis"]["multichem"] = bool(multichem_enabled) config["gis"]["sputter_coater"] = sputter_coater_enabled + print(f"""System Fingerprint: + Electron Beam: + Enabled: {config["electron"]["enabled"]} + Column Tilt: {config["electron"]["column_tilt"]} + Ion Beam: + Enabled: {config["ion"]["enabled"]} + Column Tilt: {config["ion"]["column_tilt"]} + Plasma: {config["ion"]["plasma"]} + Plasma Gas: {config["ion"]["plasma_gas"]} + Stage: + Enabled: {config["stage"]["enabled"]} + Rotation: {config["stage"]["rotation"]} + Tilt: {config["stage"]["tilt"]} + Rotation Reference: {config["stage"]["rotation_reference"]} + Rotation 180: {config["stage"]["rotation_180"]} + Manipulator: + Enabled: {config["manipulator"]["enabled"]} + GIS: + Enabled: {config["gis"]["enabled"]} + Multichem: {config["gis"]["multichem"]} + Sputter Coater: {config["gis"]["sputter_coater"]} + """) return config diff --git a/fibsem/microscope.py b/fibsem/microscope.py index 7bfadf9a..bed084ce 100644 --- a/fibsem/microscope.py +++ b/fibsem/microscope.py @@ -764,7 +764,10 @@ def __init__(self, system_settings: SystemSettings = None): self.experiment = FibsemExperiment() # logging - logging.debug({"msg": "create_microscope_client", "system_settings": system_settings.to_dict()}) + if system_settings is not None: + system_settings = system_settings.to_dict() + logging.debug({"msg": "create_microscope_client", "system_settings": system_settings}) + def reconnect(self): if not hasattr(self, "system"): @@ -820,7 +823,8 @@ def connect_to_microscope(self, ip_address: str, port: int = 7520) -> None: logging.info(f"Autoscript Client: {self.connection.service.autoscript.client.version}") logging.info(f"Autoscript Server: {self.connection.service.autoscript.server.version}") - self.reset_beam_shifts() + if self.system is not None: # tmp + self.reset_beam_shifts() def acquire_image(self, image_settings:ImageSettings) -> FibsemImage: """