Search for NXtomo(s), modify and resume processing#
H. Payno
Jan 09, 2024
15 min read
On 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 widget can be the first step of a workflow like
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 allow to find pathnames matching.
You can use it for example to research all files ending by .nx which is the expected file extentions of NXtomos.
Hint
for convenience on this example we will look 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 file under /path/to/data/
recursive=True,
)
print(files) # print files found to make sure this part works
Now all those files can contain zero, one or several NXtomo that we want to use. There is several ways to do this. The simplest is probably to use the tomwer scan factory. It can browse a file and deduce if an entry is an NXtomo or not.
Then we can add the foolowing lines on 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 concreate example of such a script and expected output
Modify NXtomo(s)#
Nox that we have a set of scan we can modify them is we like (meadata only for now). For this the simplest is to use the NXtomo library
We cannot use directly the scans from tomwer because the API doesn’t allow ‘direct persistent’ modification of the data.
Here for example we want to modify for each NXtomo the energy. For this we need to:
load the NXtomo
modify it
overwrite the NXtomo
For this we can append to the script the following:
from nxtomo.application.nxtomo import NXtomo
for scan in scans:
nx_tomo = NXtomo().load(scan.master_file, scan.entry)
# then we can now modified the field we like
nx_tomo.energy = new_value
nx_tomo.save(
file_path=scan.entry,
data_path="entry",
overwrite=True,
)
# scan.clear_caches() # clear caches of the tomwer scan object. See caution at the bottom
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 are modified we can provide this to the next widgets. For this we can define an output variable at the end of the script. In this example we want to provide a list of scan so we must define out_tomo_objs.
out_tomo_objs = scans
As much of the widgets expect a single scan object we will also need to add an instance of ‘tomo objs hub’ to the workflow to ‘split’ the list to a serie of ‘data’/’scan’ object and ensure a smooth processing.
Warning
out_tomo_obj vs out_tomo_objs
You cannot set several time out_tomo_obj in a for loop. As output variable resolution is done only at the end. In this case it will trigger downstream widgets only once with the last value set.
Caution
Tomwer scan object caches
In this example we are not loading parameters from the scan object. But for example if we add a call to scan.energy before modifying the value it will be kept in the object cache. So when you modify a scan and reuse an existing scan object the safer usually is to clear caches. using the clear_caches() function.
Example with a workflow after#
Here it can be an example of processing after NXtomo search and edition that could be trigger. 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 it execution the GUI will not be responsive. So if your processing is heavy you might experience some gui freezing.