Source code for nabu.app.compare_volumes
from math import ceil
from posixpath import join
import numpy as np
from tomoscan.io import HDF5File
from .cli_configs import CompareVolumesConfig
from ..utils import clip_circle
from .utils import parse_params_values
from ..io.utils import get_first_hdf5_entry, hdf5_entry_exists
from ..io.reader import get_hdf5_dataset_shape
[docs]
def idx_1d_to_3d(idx, shape):
nz, ny, nx = shape
x = idx % nx
idx2 = (idx - x) // nx
y = idx2 % ny
z = (idx2 - y) // ny
return (z, y, x)
[docs]
def compare_volumes(fname1, fname2, h5_path, chunk_size, do_stats, stop_at_thresh, clip_outer_circle=False):
result = None
f1 = HDF5File(fname1, "r")
f2 = HDF5File(fname2, "r")
try:
# Check that data is in the provided hdf5 path
for fname in [fname1, fname2]:
if not hdf5_entry_exists(fname, h5_path):
result = "File %s do not has data in %s" % (fname, h5_path)
return
# Check shapes
shp1 = get_hdf5_dataset_shape(fname1, h5_path)
shp2 = get_hdf5_dataset_shape(fname2, h5_path)
if shp1 != shp2:
result = "Volumes do not have the same shape: %s vs %s" % (shp1, shp2)
return
# Compare volumes
n_steps = ceil(shp1[0] / chunk_size)
for i in range(n_steps):
start = i * chunk_size
end = min((i + 1) * chunk_size, shp1[0])
data1 = f1[h5_path][start:end, :, :]
data2 = f2[h5_path][start:end, :, :]
abs_diff = np.abs(data1 - data2)
if clip_outer_circle:
for j in range(abs_diff.shape[0]):
abs_diff[j] = clip_circle(abs_diff[j], radius=0.9 * min(abs_diff.shape[1:]))
coord_argmax = idx_1d_to_3d(np.argmax(abs_diff), data1.shape)
if do_stats:
mean = np.mean(abs_diff)
std = np.std(abs_diff)
maxabs = np.max(abs_diff)
print("Chunk %d: mean = %e std = %e max = %e" % (i, mean, std, maxabs))
if stop_at_thresh is not None and abs_diff[coord_argmax] > stop_at_thresh:
coord_argmax_absolute = (start + coord_argmax[0],) + coord_argmax[1:]
result = "abs_diff[%s] = %e" % (coord_argmax_absolute, abs_diff[coord_argmax])
return
except Exception as exc:
result = "Error: %s" % (str(exc))
raise
finally:
f1.close()
f2.close()
return result
[docs]
def compare_volumes_cli():
args = parse_params_values(
CompareVolumesConfig, parser_description="A command-line utility for comparing two volumes."
)
fname1 = args["volume1"]
fname2 = args["volume2"]
h5_path = args["hdf5_path"]
if h5_path == "":
entry = args["entry"].strip() or None
if entry is None:
entry = get_first_hdf5_entry(fname1)
h5_path = join(entry, "reconstruction/results/data")
do_stats = bool(args["statistics"])
chunk_size = args["chunk_size"]
stop_at_thresh = args["stop_at"] or None
if stop_at_thresh is not None:
stop_at_thresh = float(stop_at_thresh)
res = compare_volumes(fname1, fname2, h5_path, chunk_size, do_stats, stop_at_thresh)
if res is not None:
print(res)
return 0
if __name__ == "__main__":
compare_volumes_cli()