Holo-Tomo Normalize Reconstructed Slices#

Sometimes it can be convenient to clamp the different slices (from the different distances) to the same value range. The following script achieves this goal.

Be aware that it has been tested with EDF only. It should work for NXtomo as well. You may need to replace if scan.path.endswith(“_1_”): with if scan.master_file.endswith(“_1_”):.

##################################################################
### This script will normalize a set of reconstructed slices
### from holo-tomo
### The first holo-tomo distance is expected to go through first.
### Then, from this slice reconstruction, min and max values
### will be picked to normalize the next slices.
### Warning: due to usage of 'latest_reconstructions', this
### script must be used after a 'nabu-slice' reconstruction to
### process as expected.
##################################################################

import os
import numpy
from tomoscan.factory import Factory
from nabu.misc.utils import rescale_data

if in_data is not None:
    scan = in_data

    # Warning: scan.latest_reconstructions is defined by the 'nabu slice reconstruction'.
    # So if a scan is loaded and does not go through this widget,
    # it won't be aware of slice reconstructions.
    print("Check", scan, " - latest_reconstructions", scan.latest_reconstructions)

    in_volumes = [
        Factory.create_tomo_object_from_identifier(identifier)
        for identifier in scan.latest_reconstructions
    ]

    # There may be extra volumes existing in the case of .vol files.
    # To ensure backward compatibility, filter out the ones that don't exist.
    res = []

    for vol in in_volumes:
        if os.path.exists(vol.file_path):
            res.append(vol)
    in_volumes = res

    print("Slices to be handled:", in_volumes)
    [print(vol.get_identifier().to_str()) for vol in in_volumes]

    # Retrieve the min/max from the first acquisition
    if scan.path.endswith("_1_"):
        for vol in in_volumes:
            print("Recompute min and max from", vol.file_path)
            data = vol.load_data()
            new_min, new_max = numpy.percentile(data[0], (5, 95))

    # Apply cast / rescaling data
    if "new_min" in globals() and "new_max" in globals():
        for vol in in_volumes:
            print("Normalize", vol.file_path)
            data = vol.load_data()
            # Normalize
            data = rescale_data(
                data=data,
                new_min=new_min,
                new_max=new_max,
                data_min=data.min(),
                data_max=data.max(),
            )
            # Overwrite existing data
            vol.data = data
            vol.save_data()

    out_data = scan
else:
    out_data = in_data