def save_final_images(microscope, settings, lamella_number): """Aquire and save ion beam & SEM images after complete milling stage.""" from autoscript_sdb_microscope_client.structures import (GrabFrameSettings, Rectangle) output_dir = settings["save_directory"] fullfield_cam_settings = GrabFrameSettings( reduced_area=Rectangle(0, 0, 1, 1), resolution=settings["fiducial"]["reduced_area_resolution"], dwell_time=settings["imaging"]["dwell_time"], ) if settings["imaging"]["autocontrast"]: microscope.imaging.set_active_view(2) # the ion beam view microscope.auto_functions.run_auto_cb() if settings["imaging"]["full_field_ib_images"]: original_ion_current = microscope.beams.ion_beam.beam_current.value microscope.beams.ion_beam.beam_current.value = 20e-12 # ion imaging image = grab_ion_image(microscope, fullfield_cam_settings) filename = os.path.join( output_dir, "IB_lamella{}-milling-complete.tif".format(lamella_number + 1)) image.save(filename) microscope.beams.ion_beam.beam_current.value = original_ion_current sem_adorned_image = grab_sem_image(microscope, fullfield_cam_settings) sem_fname = "SEM_lamella{}-milling-complete.tif".format(lamella_number + 1) sem_filename = os.path.join(output_dir, sem_fname) sem_adorned_image.save(sem_filename)
def create_camera_settings(imaging_settings, reduced_area=None): """Camera settings for acquiring images on the microscope. Parameters ---------- imaging_settings : dictionary User input as dictionary containing keys "resolution" and "dwell_time". reduced_area : Rectangle, optional Reduced area view for image acquisition. By default None, which will create a Rectangle(0, 0, 1, 1), which means the whole field of view will be imaged. Returns ------- GrabFrameSettings Camera acquisition settings """ from autoscript_sdb_microscope_client.structures import (GrabFrameSettings, Rectangle) if reduced_area is None: reduced_area = Rectangle(0, 0, 1, 1) camera_settings = GrabFrameSettings( resolution=imaging_settings["resolution"], dwell_time=imaging_settings["dwell_time"], reduced_area=reduced_area, ) return camera_settings
def fiducial_reduced_area_rect(fiducial_relative_center, fiducial_relative_size): """Return autoscript Rectangle object describing the fiducial reduced area Returns ------- Autoscript Rectangle Fiducial reduced area rectangle, in relative units. """ from autoscript_sdb_microscope_client.structures import Rectangle width, height = fiducial_relative_size top_left_x = fiducial_relative_center[0] - (width / 2) top_left_y = fiducial_relative_center[1] - (height / 2) if top_left_x < 0: top_left_x = 0 if top_left_x > 1: raise ValueError( "top_left_x relative coordinate cannot be larger than 1") if top_left_y < 0: top_left_y = 0 if top_left_y > 1: raise ValueError( "top_left_y relative coordinate cannot be larger than 1") # create the relative rectangle fiducial_reduced_area = Rectangle(top_left_x, top_left_y, width, height) print("fiducial_reduced_area", fiducial_reduced_area) return fiducial_reduced_area
def run_drift_corrected_milling(microscope, correction_interval, reduced_area=None): """ Parameters ---------- microscope : Autoscript microscope object correction_interval : Time in seconds between drift correction realignment reduced_area : Autoscript Rectangle() object Describes the reduced area view in relative coordinates, with the origin in the top left corner. Default value is None, which will create a Rectangle(0, 0, 1, 1), which means the imaging will use the whole field of view. """ from autoscript_core.common import ApplicationServerException from autoscript_sdb_microscope_client.structures import (GrabFrameSettings, Rectangle) if reduced_area is None: reduced_area = Rectangle(0, 0, 1, 1) s = GrabFrameSettings(reduced_area=reduced_area) reference_image = microscope.imaging.grab_frame(s) # start drift corrected patterning (is a blocking function, not asynchronous) microscope.patterning.start() while microscope.patterning.state == "Running": time.sleep(correction_interval) try: microscope.patterning.pause() except ApplicationServerException: continue else: new_image = microscope.imaging.grab_frame(s) realign(microscope, new_image, reference_image) microscope.patterning.resume()
def test_create_camera_settings(microscope): from autoscript_sdb_microscope_client.structures import GrabFrameSettings imaging_settings = {"resolution": "1536x1024", "dwell_time": 1e-6} result = autolamella.acquire.create_camera_settings(imaging_settings, reduced_area=Rectangle( 0, 0, 1, 1)) assert isinstance(result, GrabFrameSettings)
def set_sem_image(self, microscope, settings): from autoscript_sdb_microscope_client.structures import ( GrabFrameSettings, Rectangle, ) microscope.imaging.set_active_view(1) # SEM beam view camera_settings = GrabFrameSettings( reduced_area=Rectangle(0, 0, 1, 1), resolution=settings["imaging"]["resolution"], ) self.sem_image = microscope.imaging.grab_frame(camera_settings) microscope.imaging.set_active_view(2) # Restore ion beam view return self.sem_image
def grab_images(microscope, settings, my_lamella, prefix="", suffix=""): """Aquire and save images, with optional autocontrast. Parameters ---------- microscope : Autoscript microscope object. settings : dictionary Dictionary continaing user input parameters. my_lamella : Lamella object prefix : str, optional Prefix to use when saving image files, by default "" suffix : str, optional Suffix to use when saving image files, by default "" Returns ------- AdornedImage The reduced area ion beam image (shows just the fiducial marker). """ from autoscript_sdb_microscope_client.structures import (GrabFrameSettings, Rectangle) output_dir = settings["save_directory"] # Reduced area images (must reset camera settings each time, because different samples have different reduced areas) camera_settings = GrabFrameSettings( reduced_area=my_lamella.fiducial_reduced_area, resolution=settings["fiducial"]["reduced_area_resolution"], dwell_time=settings["imaging"]["dwell_time"], ) fullfield_cam_settings = GrabFrameSettings( reduced_area=Rectangle(0, 0, 1, 1), resolution=settings["fiducial"]["reduced_area_resolution"], dwell_time=settings["imaging"]["dwell_time"], ) # Optional autocontrast (you cannot do autocontrast on a reduced area) if settings["imaging"]["autocontrast"]: microscope.imaging.set_active_view(2) # the ion beam view autocontrast(microscope) image = grab_ion_image(microscope, camera_settings) filename = os.path.join(output_dir, prefix + "_" + suffix + ".tif") image.save(filename) # Optional full field images acquire_many_images = settings["imaging"]["full_field_ib_images"] if acquire_many_images: fullfield_image = grab_ion_image(microscope, fullfield_cam_settings) fname_fullfield = prefix + "_FullField_" + suffix + ".tif" filename_fullfield = os.path.join(output_dir, fname_fullfield) fullfield_image.save(filename_fullfield) return image
def camera_settings(): imaging_settings = {"resolution": "3072x2048", "dwell_time": 1e-6} camera_settings = autolamella.acquire.create_camera_settings( imaging_settings, reduced_area=Rectangle(0, 0, 1, 1)) return camera_settings
def add_single_sample(microscope, settings): """Create a single lamella object. Parameters ---------- microscope : Autoscript microscope object. settings : Dictionary of user input argument settings. Returns ------- my_lamella A single Lamella() object. """ from autoscript_core.common import ApplicationServerException from autoscript_sdb_microscope_client.structures import (GrabFrameSettings, Rectangle) autolamella.autoscript.reset_state(microscope, settings) demo_mode = settings["demo_mode"] acquire_many_images = settings["imaging"]["full_field_ib_images"] # Reset microscope state autolamella.autoscript.reset_state(microscope, settings) microscope.beams.ion_beam.beam_current.value = settings["lamella"][ "milling_current"] # Optional autocontrast if settings["imaging"]["autocontrast"]: microscope.imaging.set_active_view(2) # the ion beam view autolamella.acquire.autocontrast(microscope) # Take full field image full_field_camera_settings = autolamella.acquire.create_camera_settings( settings["imaging"], reduced_area=Rectangle(0, 0, 1, 1)) original_image = grab_ion_image(microscope, full_field_camera_settings) # Select fiducial posiion print("Please select where to put a fiducial marker.") my_fiducial = autolamella.fiducial.fiducial( microscope, original_image, settings["fiducial"]["fiducial_length"], settings["fiducial"]["fiducial_width"], settings["fiducial"]["fiducial_image_size_x"], settings["fiducial"]["fiducial_image_size_y"], settings["fiducial"]["fiducial_milling_depth"], ) if my_fiducial is None: print("No fiducial location selected, cancelling.") microscope.patterning.clear_patterns() return # fiducial_coord_realspace, fiducial_coord_relative, fiducial_coord_pixels = ( my_fiducial) pixelsize_x = original_image.metadata.binary_result.pixel_size.x fiducial_image_relative_size = [ settings["fiducial"]["fiducial_image_size_x"] / (original_image.width * pixelsize_x), settings["fiducial"]["fiducial_image_size_y"] / (original_image.height * pixelsize_x), ] reduced_area_fiducial = autolamella.fiducial.fiducial_reduced_area_rect( fiducial_coord_relative, fiducial_image_relative_size) camera_settings = autolamella.acquire.create_camera_settings( settings["imaging"], reduced_area=reduced_area_fiducial) cropped_original_image = grab_ion_image(microscope, camera_settings) my_lamella = Lamella(microscope) my_lamella.fiducial_image_relative_size = fiducial_image_relative_size my_fiducial = my_lamella.set_fiducial( cropped_original_image, fiducial_coord_realspace, fiducial_coord_relative, fiducial_coord_pixels, reduced_area_fiducial, ) # Select the lamella position print("Please select the center point of your lamella.") my_lamella.original_image = original_image lamella_center = my_lamella.set_center(original_image, settings) if lamella_center == []: print("No lamella position selected, cancelling.") microscope.patterning.clear_patterns() return # Ask user for decision message = "Are you happy with this position? [y]/n\n" if ask_user(message, default="yes"): message = "Do you want to mill a fiducial marker here? [y]/n\n" if ask_user(message, default="yes"): print("Milling fiducial marker...") if not demo_mode: microscope.beams.ion_beam.beam_current.value = settings[ "fiducial"]["fiducial_milling_current"] microscope.imaging.set_active_view(2) # the ion beam view try: microscope.patterning.run() except ApplicationServerException: logging.error( "ApplicationServerException: could not mill!") microscope.patterning.clear_patterns() return # returns None which gets stripped from sample list if acquire_many_images: full_field_camera_settings = GrabFrameSettings( reduced_area=Rectangle(0, 0, 1, 1), resolution=settings["imaging"]["resolution"], dwell_time=settings["imaging"]["dwell_time"], ) microscope.auto_functions.run_auto_cb() reference_image = grab_ion_image(microscope, full_field_camera_settings) my_lamella.reference_image = reference_image camera_settings = GrabFrameSettings( reduced_area=reduced_area_fiducial, resolution=settings["fiducial"]["reduced_area_resolution"], dwell_time=settings["imaging"]["dwell_time"], ) cropped_reference_image = grab_ion_image(microscope, camera_settings) message = "Do you want to re-mill the fiducial marker? y/[n]\n" if ask_user(message, default="no"): print("Milling fiducial marker again...") if not demo_mode: microscope.imaging.set_active_view(2) # the ion beam view try: microscope.patterning.run() except ApplicationServerException: logging.error( "ApplicationServerException: could not mill") microscope.patterning.clear_patterns() return # returns None which gets stripped from sample list if acquire_many_images: full_field_camera_settings = GrabFrameSettings( reduced_area=Rectangle(0, 0, 1, 1), resolution=settings["imaging"]["resolution"], dwell_time=settings["imaging"]["dwell_time"], ) microscope.auto_functions.run_auto_cb() reference_image = grab_ion_image( microscope, full_field_camera_settings) my_lamella.reference_image = reference_image microscope.patterning.clear_patterns() else: print("Ok, deleting those milling patterns.") microscope.patterning.clear_patterns() return # returns None, which gets stripped from sample list later # Continue on camera_settings = GrabFrameSettings( reduced_area=reduced_area_fiducial, resolution=settings["fiducial"]["reduced_area_resolution"], dwell_time=settings["imaging"]["dwell_time"], ) cropped_reference_image = grab_ion_image(microscope, camera_settings) my_lamella.set_fiducial( cropped_reference_image, fiducial_coord_realspace, fiducial_coord_relative, fiducial_coord_pixels, reduced_area_fiducial, ) if not acquire_many_images: my_lamella.reference_image = cropped_reference_image my_lamella.set_sem_image(microscope, settings) my_lamella.set_custom_milling_depth() return my_lamella