{ "cells": [ { "cell_type": "markdown", "id": "ffb84091-b850-4054-bcbf-b17bc9e1f517", "metadata": {}, "source": [ "# Create instrument.detector.data from TIFF files\n", "\n", "If your acquisition was saved as `.tiff` files you can reuse them for the `instrument/detector/data` dataset.\n" ] }, { "cell_type": "markdown", "id": "04ffec29-1d3c-4de8-8f6e-a5d85a6a57ff", "metadata": {}, "source": [ "## Create an NXtomo\n", "\n", "See the \"Create an NXtomo (from scratch)\" tutorial for the initial steps.\n", "\n", "Here we bootstrap an NXtomo with one dark frame and one flat frame at the beginning, followed by ten projections.\n" ] }, { "cell_type": "code", "execution_count": null, "id": "49758bba-6dfa-4f70-8c4c-07bb1210ce9a", "metadata": {}, "outputs": [], "source": [ "import pint\n", "import numpy\n", "from nxtomo import NXtomo\n", "from nxtomo.nxobject.nxdetector import ImageKey\n", "\n", "ureg = pint.get_application_registry()\n", "\n", "image_key_control = numpy.concatenate(\n", " [\n", " [ImageKey.DARK_FIELD] * 1,\n", " [ImageKey.FLAT_FIELD] * 1,\n", " [ImageKey.PROJECTION] * 10,\n", " ]\n", ")\n", "\n", "my_nxtomo = NXtomo()\n", "my_nxtomo.instrument.detector.image_key_control = numpy.concatenate(\n", " [\n", " [ImageKey.DARK_FIELD] * 1,\n", " [ImageKey.FLAT_FIELD] * 1,\n", " [ImageKey.PROJECTION] * 10,\n", " ]\n", ")\n", "my_nxtomo.sample.rotation_angle = (\n", " numpy.concatenate(\n", " [\n", " [0, 0],\n", " numpy.linspace(0, 360, 10),\n", " ]\n", " )\n", " * ureg.degree\n", ")\n", "# ..." ] }, { "cell_type": "markdown", "id": "07227061-08f5-4ccf-bd2b-98279a191e40", "metadata": {}, "source": [ "## Append the TIFF files\n", "\n", "To append a series of TIFF files we can use the helper function `create_detector_dataset_from_tiff`.\n", "This function creates one HDF5 virtual source per TIFF file.\n", "\n", "Each virtual source requires an external dataset entry that defines how to access the raw data. The external dataset is then referenced by the HDF5 virtual dataset, giving access to your TIFF files.\n", "\n", "To create the external datasets, `create_detector_dataset_from_tiff` needs an HDF5 group (the output group), which should be the file containing the NXtomo.\n", "\n", "Note: the creation of the HDF5 virtual dataset is handled by the library when you save the NXtomo to disk.\n" ] }, { "cell_type": "code", "execution_count": null, "id": "8296baa3-4e74-4817-80f6-96b345742356", "metadata": {}, "outputs": [], "source": [ "import h5py\n", "import os\n", "from nxtomo.utils.utils import create_detector_dataset_from_tiff\n", "\n", "output_file = \"my_nxtomo_with_tiff.nx\"\n", "with h5py.File(output_file, mode=\"w\") as h5f:\n", " external_dataset_group = h5f.require_group(\"external_datasets\")\n", "\n", " assert os.path.exists(\"resources/raw_tiff_files/\")\n", " my_nxtomo.instrument.detector.data = create_detector_dataset_from_tiff(\n", " tiff_files=(\n", " \"resources/raw_tiff_files/dark.tif\",\n", " \"resources/raw_tiff_files/flat_0000.tif\",\n", " \"resources/raw_tiff_files/projection_0000.tif\",\n", " \"resources/raw_tiff_files/projection_0001.tif\",\n", " \"resources/raw_tiff_files/projection_0002.tif\",\n", " \"resources/raw_tiff_files/projection_0003.tif\",\n", " \"resources/raw_tiff_files/projection_0004.tif\",\n", " \"resources/raw_tiff_files/projection_0005.tif\",\n", " \"resources/raw_tiff_files/projection_0006.tif\",\n", " \"resources/raw_tiff_files/projection_0007.tif\",\n", " \"resources/raw_tiff_files/projection_0008.tif\",\n", " \"resources/raw_tiff_files/projection_0009.tif\",\n", " ),\n", " external_dataset_group=external_dataset_group,\n", " relative_link=False,\n", " )" ] }, { "cell_type": "markdown", "id": "99e2b6f0-e9ae-49a1-9950-954ab4f7e8e4", "metadata": {}, "source": [ "### Notes on relative versus absolute links\n", "\n", "The most robust approach is to use relative links so the NXtomo file can travel with the `.tiff` files. However, external datasets currently resolve relative links against the current working directory instead of the file location.\n", "\n", "Tomotools handles this internally, but other software (such as silx) may not, because the behaviour should be fixed at the HDF5 layer. Be aware that these links can appear broken when they are relative. This issue does not occur when using absolute links.\n" ] }, { "cell_type": "markdown", "id": "aad6d713-39c7-4f93-be53-87ae96c7070c", "metadata": {}, "source": [ "## Save the final NXtomo\n" ] }, { "cell_type": "code", "execution_count": null, "id": "b9b4da86-58cb-446a-bd42-e241aa4359ed", "metadata": {}, "outputs": [], "source": [ "my_nxtomo.save(output_file, \"entry0000\")" ] }, { "cell_type": "markdown", "id": "a55f8933-6f59-4e59-b8ce-8056f17ed4f5", "metadata": {}, "source": [ "You can now use this NXtomo like any other NXtomo and process it with nabu or other tools.\n" ] }, { "cell_type": "markdown", "id": "46f5dc6c-1588-4813-94fd-30d3628aea73", "metadata": {}, "source": [ "## Note on performance\n", "\n", "Creating one external link per frame has a noticeable performance cost.\n", "\n", "When building a sinogram the pipeline must open each file and read a single line, which is expensive.\n" ] }, { "cell_type": "markdown", "id": "7ec41c95-6b4f-4176-8aa6-ba95a12e3f7b", "metadata": {}, "source": [ "## Remove the output file\n" ] }, { "cell_type": "code", "execution_count": null, "id": "6c880208-cfc2-4c20-ac5d-1a62c8fed593", "metadata": {}, "outputs": [], "source": [ "os.remove(output_file)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.2" } }, "nbformat": 4, "nbformat_minor": 5 }