.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/plot_lext_zenodo.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_plot_lext_zenodo.py: Olympus LEXT Files From Zenodo ============================== This example downloads Olympus LEXT OLS4100 confocal microscope data from Zenodo, extracts the ``.lext`` files, converts each intensity channel to a display image, enhances it, and adds a scale bar. Data source ----------- Title: Raw data on tribometry of laser structured copper surfaces Authors: Sebastian Suarez, Bruno Alderete, Fabian Bonner, Silas Daniel Schütz, Frank Thomas Mücklich Zenodo: https://zenodo.org/records/17814735 .. GENERATED FROM PYTHON SOURCE LINES 21-105 .. code-block:: Python import os import shutil from pathlib import Path from urllib.request import urlopen from xml.etree import ElementTree from zipfile import ZipFile import matplotlib.pyplot as plt import numpy as np from PIL import Image import tifffile from micromechanics.tif import Tif DATA_URL = "https://zenodo.org/api/records/17814735/files/Files%20CLSM.zip/content" EXAMPLE_DIR = Path(__file__).resolve().parent if "__file__" in globals() else Path.cwd().resolve() DATA_DIR = EXAMPLE_DIR / "_downloads" / "lext_zenodo_17814735" ZIP_PATH = DATA_DIR / "Files CLSM.zip" LEXT_DIR = DATA_DIR / "Files CLSM" def download_and_unpack() -> Path: """Download and unpack the Zenodo archive if the data are not present.""" DATA_DIR.mkdir(parents=True, exist_ok=True) if not ZIP_PATH.exists(): print("Downloading", DATA_URL) temporary_path = ZIP_PATH.with_suffix(".zip.part") with urlopen(DATA_URL, timeout=60) as response, temporary_path.open("wb") as file_handle: shutil.copyfileobj(response, file_handle) temporary_path.replace(ZIP_PATH) if not any(LEXT_DIR.glob("*.lext")): print("Unpacking", ZIP_PATH) with ZipFile(ZIP_PATH) as archive: archive.extractall(DATA_DIR) return LEXT_DIR def processLext(path: Path, channel: str = "intensity") -> Path: """Read the lext file, create a display image, and save it as png.""" with tifffile.TiffFile(path) as tif: lext_description = tif.pages[0].description or "" channels = {"intensity": 0} for page_index, page in enumerate(tif.pages): description = (page.description or "").strip() if description == "INTENSITY": channels["intensity"] = page_index elif description == "HEIGHT": channels["height"] = page_index print(" Available channels:", ", ".join(channels)) data = tif.pages[channels[channel]].asarray() root = ElementTree.fromstring(lext_description) tag_name = "HeightDataPerPixelX" if channel == "height" else "IntensityDataPerPixelX" tag = root.find(f".//{tag_name}") if tag is None or tag.text is None: raise ValueError(f"Could not find {tag_name} in {path}") pixel_size = float(tag.text) / 1_000_000.0 # Olympus LEXT stores lateral spacing in picometers in these files. values = data.astype(np.float64, copy=False) low, high = np.percentile(values, (0.5, 99.5)) if high <= low: high = low + 1.0 scaled = np.clip((values - low) / (high - low), 0.0, 1.0) image = Image.fromarray((scaled * 255).astype(np.uint8)).convert("L") # custom resizing # targetWidthPx = round(640 / pixel_size) # make image exactly 640um wide # if image.size[0] > targetWidthPx: # image = image.crop((0, 0, targetWidthPx, image.size[1])) # targetHeightPx = round(480 / pixel_size) # make image exactly 480um tall # if image.size[1] > targetHeightPx: # image = image.crop((0, 0, image.size[0], targetHeightPx)) tif = Tif() tif.setData(image, pixel_size) tif.enhance("adaptive") tif.addScaleBar("BR", scale=int(tif.width / 7.0)) output_path = path.with_suffix(".png") tif.image.convert("RGB").save(output_path) print(f" pixelSize={pixel_size:g} um, width={tif.width:g} um, height={tif.image.size[1]*pixel_size:g} um") return output_path .. GENERATED FROM PYTHON SOURCE LINES 106-109 Download the public Zenodo archive only once, unpack it, and process all LEXT files in the archive. Generated PNG files are written next to the extracted measurement files under ``docs/source/examples/_downloads/``. .. GENERATED FROM PYTHON SOURCE LINES 109-118 .. code-block:: Python lext_dir = download_and_unpack() output_paths = [] for file_name in sorted(os.listdir(lext_dir)): if not file_name.endswith(".lext"): continue print("Processing", file_name) output_paths.append(processLext(lext_dir / file_name, "intensity")) .. rst-class:: sphx-glr-script-out .. code-block:: none Downloading https://zenodo.org/api/records/17814735/files/Files%20CLSM.zip/content Unpacking /home/runner/work/micromechanics/micromechanics/docs/source/examples/_downloads/lext_zenodo_17814735/Files CLSM.zip Processing 200720_cu 10 15deg 50 3x.lext Available channels: intensity, height widthPixel 1024 Pixel size 0.08333333333333333 [um] Picture width 85.33333333333333 [um] pixelSize=0.0833333 um, width=85.3333 um, height=85.3333 um Processing 200720_cu 2 0deg 50 3x.lext Available channels: intensity, height widthPixel 1024 Pixel size 0.08333333333333333 [um] Picture width 85.33333333333333 [um] pixelSize=0.0833333 um, width=85.3333 um, height=85.3333 um Processing 200720_cu 2 15deg 50 3x.lext Available channels: intensity, height widthPixel 1024 Pixel size 0.08333333333333333 [um] Picture width 85.33333333333333 [um] pixelSize=0.0833333 um, width=85.3333 um, height=85.3333 um Processing 200720_cu 2 30deg 50 3x.lext Available channels: intensity, height widthPixel 1024 Pixel size 0.08333333333333333 [um] Picture width 85.33333333333333 [um] pixelSize=0.0833333 um, width=85.3333 um, height=85.3333 um Processing 200720_cu 2 45deg 50 3x.lext Available channels: intensity, height widthPixel 1024 Pixel size 0.08333333333333333 [um] Picture width 85.33333333333333 [um] pixelSize=0.0833333 um, width=85.3333 um, height=85.3333 um Processing 200720_cu 7.5 15deg 50 3x.lext Available channels: intensity, height widthPixel 1024 Pixel size 0.08333333333333333 [um] Picture width 85.33333333333333 [um] pixelSize=0.0833333 um, width=85.3333 um, height=85.3333 um .. GENERATED FROM PYTHON SOURCE LINES 119-120 Display the first processed image in the generated documentation page. .. GENERATED FROM PYTHON SOURCE LINES 120-124 .. code-block:: Python first_image = Image.open(output_paths[0]) plt.imshow(first_image) plt.axis("off") .. image-sg:: /auto_examples/images/sphx_glr_plot_lext_zenodo_001.png :alt: plot lext zenodo :srcset: /auto_examples/images/sphx_glr_plot_lext_zenodo_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none (np.float64(-0.5), np.float64(1023.5), np.float64(1023.5), np.float64(-0.5)) .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 15.947 seconds) .. _sphx_glr_download_auto_examples_plot_lext_zenodo.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_lext_zenodo.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_lext_zenodo.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_lext_zenodo.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_