Examples¶
Hologram from tif file¶
This example illustrates how to retrieve phase and amplitude from a hologram stored as a tif file. The experimental hologram is a U.S. Air Force test target downloaded from the Submersible Holographic Astrobiology Microscope with Ultraresolution (SHAMU) project [BBL+17]. The values for pixel resolution, wavelength, and reconstruction distance are taken from the corresponding Python example.
The object returned by the
get_qpimage <qpformat.file_formats.dataset.SingleData.get_qpimage()
function is an instance of qpimage.QPImage
which allows for field refocusing. The refocused QPImage is
background-corrected using a polynomial fit to the phase data at locations
where the amplitude data is not attenuated (bright regions in the amplitude
image).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | import urllib.request
import os
import matplotlib.pylab as plt
import qpformat
# load the experimental data
dl_loc = "https://github.com/bmorris3/shampoo/raw/master/data/"
dl_name = "USAF_test.tif"
if not os.path.exists(dl_name):
urllib.request.urlretrieve(dl_loc + dl_name, dl_name)
ds = qpformat.load_data(dl_name,
# manually set meta data
meta_data={"pixel size": 3.45e-6,
"wavelength": 405e-9,
"medium index": 1},
# set filter size to 1/2 (defaults to 1/3)
# which increases the image resolution
holo_kw={"filter_size": .5})
# retrieve the qpimage.QPImage instance
qpi = ds.get_qpimage()
# refocus `qpi` to 0.03685m
qpi_foc = qpi.refocus(0.03685)
# perform an offset-based amplitude correction
qpi_foc.compute_bg(which_data="amplitude",
fit_profile="offset",
fit_offset="mode",
border_px=10,
)
# perform a phase correction using
# - those pixels that are not dark in the amplitude image (amp_bin) and
# - a 2D second order polynomial fit to the phase data
amp_bin = qpi_foc.amp > 1 # bright regions
qpi_foc.compute_bg(which_data="phase",
fit_profile="poly2o",
from_binary=amp_bin,
)
# plot results
plt.figure(figsize=(8, 3.5))
# ampltitude
ax1 = plt.subplot(121, title="amplitude")
map1 = plt.imshow(qpi_foc.amp, cmap="gray")
plt.colorbar(map1, ax=ax1, fraction=.0455, pad=0.04)
# phase in interval [-1rad, 1rad]
ax2 = plt.subplot(122, title="phase [rad]")
map2 = plt.imshow(qpi_foc.pha, vmin=-1, vmax=1)
plt.colorbar(map2, ax=ax2, fraction=.0455, pad=0.04)
# disable axes
[ax.axis("off") for ax in [ax1, ax2]]
plt.tight_layout()
plt.show()
|
HyperSpy hologram file format¶
This example demonstrates the import of hologram images in the HyperSpy hdf5 file format. The off-axis electron hologram shows an electrically biased Fe needle [MLFDB15]. The corresponding HyperSpy demo can be found here.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | import urllib.request
import os
import matplotlib.pylab as plt
import qpformat
# load the experimental data
dl_loc = "https://github.com/hyperspy/hyperspy/raw/RELEASE_v1.3/" \
+ "hyperspy/misc/holography/example_signals/"
dl_name = "01_holo_Vbp_130V_0V_bin2_crop.hdf5"
if not os.path.exists(dl_name):
urllib.request.urlretrieve(dl_loc + dl_name, dl_name)
ds = qpformat.load_data(dl_name,
holo_kw={
# reduces ringing artifacts in the amplitude image
"filter_name": "smooth disk",
# select correct sideband
"sideband": -1,
})
# retrieve the qpimage.QPImage instance
qpi = ds.get_qpimage(0)
# plot results
plt.figure(figsize=(8, 3.5))
# ampltitude
ax1 = plt.subplot(121, title="amplitude")
map1 = plt.imshow(qpi.amp, cmap="gray")
plt.colorbar(map1, ax=ax1, fraction=.0455, pad=0.04)
# phase in interval [-1rad, 1rad]
ax2 = plt.subplot(122, title="phase [rad]")
map2 = plt.imshow(qpi.pha)
plt.colorbar(map2, ax=ax2, fraction=.0455, pad=0.04)
# disable axes
[ax.axis("off") for ax in [ax1, ax2]]
plt.tight_layout()
plt.show()
|
Conversion of external file formats to .npy files¶
Sometimes the data recorded are not in a file format supported by qpformat or it is not feasible to implement a reader class for a very unique data set. In this example, QPI data, stored as a tuple of files (“*_intensity.txt” and “*_phase.txt”) with commas as decimal separators, are converted to the numpy file format which is supported by qpformat.
This example must be executed with a directory as an
command line argument, i.e.
python convert_txt2npy.py /path/to/folder/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | import pathlib
import sys
import numpy as np
def get_paths(folder):
'''Return *_phase.txt files in `folder`'''
folder = pathlib.Path(folder).resolve()
files = folder.rglob("*_phase.txt")
return sorted(files)
def load_file(path):
'''Load a txt data file'''
path = pathlib.Path(path)
data = path.open().readlines()
# remove comments and empty lines
data = [l for l in data if len(l.strip()) and not l.startswith("#")]
# determine data shape
n = len(data)
m = len(data[0].strip().split())
res = np.zeros((n, m), dtype=np.dtype(float))
# write data to array, replacing comma with point decimal separator
for ii in range(n):
res[ii] = np.array(data[ii].strip().replace(",", ".").split(),
dtype=float)
return res
def load_field(path):
'''Load QPI data using *_phase.txt files'''
path = pathlib.Path(path)
phase = load_file(path)
inten = load_file(path.parent / (path.name[:-10] + "_intensity.txt"))
ampli = np.sqrt(inten)
return ampli * np.exp(1j * phase)
if __name__ == "__main__":
path = pathlib.Path(sys.argv[-1])
if not path.is_dir():
raise ValueError("Command line argument must be directory!")
# output directory
pout = path.parent / (path.name + "_npy")
pout.mkdir(exist_ok=True)
# get input *_phase.txt files
files = get_paths(path)
# conversion
for ff in files:
field = load_field(ff)
np.save(str(pout / (ff.name[:-10] + ".npy")), field)
|
Conversion of external holograms to .tif files¶
Qpformat can load hologram data from .tif image files. If your experimental hologram data are stored in a different file format, you can either request its implementation in qpformat by `creating an issue<https://github.com/RI-imaging/qpformat/issues/new>`_ or you can modify this example script to your needs.
This example must be executed with a directory as an
command line argument, i.e.
python convert_txt2tif.py /path/to/folder/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | import pathlib
import sys
import numpy as np
from skimage.external import tifffile
# File names ending with these strings are ignored
ignore_endswith = ['.bmp', '.npy', '.opj', '.png', '.pptx', '.py', '.svg',
'.tif', '.txt', '_RIdist', '_parameter', '_parameter_old',
'_phase', 'n_array', 'n_array_real', '~']
# uncomment this line to keep background hologram files
ignore_endswith += ['_bg']
def get_paths(folder, ignore_endswith=ignore_endswith):
'''Return hologram file paths
Parameters
----------
folder: str or pathlib.Path
Path to search folder
ignore_endswith: list
List of filename ending strings indicating which
files should be ignored.
'''
folder = pathlib.Path(folder).resolve()
files = folder.rglob("*")
for ie in ignore_endswith:
files = [ff for ff in files if not ff.name.endswith(ie)]
return sorted(files)
if __name__ == "__main__":
path = pathlib.Path(sys.argv[-1])
if not path.is_dir():
raise ValueError("Command line argument must be directory!")
# output directory
pout = path.parent / (path.name + "_tif")
pout.mkdir(exist_ok=True)
# get input hologram files
files = get_paths(path)
# conversion
for ff in files:
# convert image data to uint8 (most image sensors)
hol = np.loadtxt(str(ff), dtype=np.uint8)
tifout = str(pout / (ff.name + ".tif"))
# compress image data
tifffile.imsave(tifout, hol, compress=9)
|