Search for NXtomo(s), Modify, and Resume Processing#
H. Payno
Jan 09, 2024
15 min read
In this example, we will see how to:
Search for NXtomo(s)
Modify the NXtomo
Trigger downstream widgets
The script to search, modify, and trigger downstream widgets can be the first step of a workflow like this:
Hint
To edit the script, double-click on the widget.
Search for NXtomo(s)#
It can be the first step of a workflow.
Python comes with the glob module, which allows us to find pathnames matching a specified pattern.
You can use it, for example, to search for all files ending with .nx, which is the expected file extension for NXtomos.
Hint
For convenience, in this example, we will search everywhere at a given location using the ‘**’ pattern. But you can also search at a specific level/depth instead.
from glob import glob
import os
files = glob(
os.path.join("/path/to/data/**", "*.nx"), # Search for all .nx files under /path/to/data/
recursive=True,
)
print(files) # Print found files to ensure this part works
Now, these files can contain zero, one, or several NXtomo objects that we want to use. There are several ways to handle this. The simplest is probably to use the Tomwer ScanFactory. It can browse a file and deduce if an entry is a NXtomo or not.
We can add the following lines to the script:
from glob import glob
from tomwer.core.scan.scanfactory import ScanFactory
# Retrieve all scans
scans = []
for file_ in files:
scans.extend(ScanFactory.create_scan_objects(file_))
# Print found scans
print("Found scans", [scan.get_identifier().short_description() for scan in scans])
Here is a concrete example of such a script and the expected output:
Modify NXtomo(s)#
Now that we have a set of scans, we can modify them as needed (metadata only for now). The simplest way to do this is to use the NXtomo library.
We cannot use the scans directly from Tomwer because the API doesn’t allow “direct persistent” modification of the data.
For example, to modify the energy value of each NXtomo, we need to:
Load the NXtomo
Modify it
Overwrite the NXtomo
You can append the following lines to the script:
from nxtomo.application.nxtomo import NXtomo
for scan in scans:
nx_tomo = NXtomo().load(scan.master_file, scan.entry)
# Modify the field as needed
nx_tomo.energy = new_value
nx_tomo.save(
file_path=scan.entry,
data_path="entry",
overwrite=True,
)
# Clear caches to ensure coherence
scan.clear_caches()
See also
A tutorial explaining how to edit NXtomo can be found here: https://tomotools.gitlab-pages.esrf.fr/nxtomo/tutorials/nx_tomo_tutorial.html#edit-an-NXtomo
Resume Processing / Trigger Downstream Widgets#
Now that the NXtomo objects are modified, we can pass them to the next widgets. For this, we define an output variable at the end of the script. In this example, we want to provide a list of scans, so we define out_tomo_objs.
out_tomo_objs = scans
Since many widgets expect a single scan object, we also need to add a ‘tomo objs hub’ instance to the workflow to “split” the list into a series of data/scan objects, ensuring smooth processing.
Warning
out_tomo_obj vs out_tomo_objs
You cannot set out_tomo_obj multiple times in a loop. Output variable resolution happens only at the end, so it will trigger downstream widgets only once, using the last value set.
Caution
Tomwer Scan Object Caches
In this example, we are not loading parameters from the scan object. But if, for example, we added a call to scan.energy before modifying the value, it would be cached. When you modify a scan and reuse an existing scan object, it is usually safer to clear caches using the clear_caches() function.
Example with a Workflow After#
Here is an example of a workflow after NXtomo search and modification. In this case, it will build a volume for each scan.
Warning
GUI Freeze
The Python script will be executed in the main Qt thread. As a consequence, during its execution, the GUI will not be responsive. If your processing is heavy, you might experience some GUI freezing.