holo-tomo normalize reconstructed slices#

If can sometimes be convenient to clamp the different slices (from the different distances) to the same value range. This is the goal of the following script.

Be aware that it has been tested with EDF only. Should work for NXtomo as well. Maybe the if scan.path.endswith(“_1_”): will need to be replaced by 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 value min and max values
### will be picked to normlaize next slices.
### Warning: due to usage of 'latest_reconstructions' this
### script must be put 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 not go trhough this widget
    # he won't be aware about 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
    ]

    # looks like there is some extra volume existing in the case of .vol - to ensure some backward compatibility. Filter the one not existing
    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 / reclaming 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