Load image from JPK Instruments .jpk files.
Parameters:
Name |
Type |
Description |
Default |
file_path
|
Path | str
|
|
required
|
channel
|
str
|
The channel to extract from the .jpk file.
|
required
|
Returns:
Type |
Description |
tuple[NDArray, float]
|
A tuple containing the image and its pixel to nanometre scaling value.
|
Raises:
Type |
Description |
FileNotFoundError
|
If the file is not found.
|
KeyError
|
If the channel is not found in the file.
|
Examples:
Load height trace channel from the .jpk file. 'height_trace' is the default channel name.
>>> from AFMReader.jpk import load_jpk
>>> image, pixel_to_nanometre_scaling_factor = load_jpk(file_path="./my_jpk_file.jpk", channel="height_trace")
Source code in AFMReader/jpk.py
| def load_jpk(file_path: Path | str, channel: str) -> tuple[np.ndarray, float]:
"""
Load image from JPK Instruments .jpk files.
Parameters
----------
file_path : Path | str
Path to the .jpk file.
channel : str
The channel to extract from the .jpk file.
Returns
-------
tuple[npt.NDArray, float]
A tuple containing the image and its pixel to nanometre scaling value.
Raises
------
FileNotFoundError
If the file is not found.
KeyError
If the channel is not found in the file.
Examples
--------
Load height trace channel from the .jpk file. 'height_trace' is the default channel name.
>>> from AFMReader.jpk import load_jpk
>>> image, pixel_to_nanometre_scaling_factor = load_jpk(file_path="./my_jpk_file.jpk", channel="height_trace")
"""
logger.info(f"Loading image from : {file_path}")
file_path = Path(file_path)
filename = file_path.stem
try:
tif = tifffile.TiffFile(file_path)
except FileNotFoundError:
logger.error(f"[{filename}] File not found : {file_path}")
raise
# Obtain channel list for all channels in file
channel_list = {}
for i, page in enumerate(tif.pages[1:]): # [0] is thumbnail
available_channel = page.tags["32848"].value # keys are hexadecimal values
if page.tags["32849"].value == 0: # whether img is trace or retrace
tr_rt = "trace"
else:
tr_rt = "retrace"
channel_list[f"{available_channel}_{tr_rt}"] = i + 1
try:
channel_idx = channel_list[channel]
except KeyError:
logger.error(f"{channel} not in channel list: {channel_list}")
raise
# Get image and if applicable, scale it
channel_page = tif.pages[channel_idx]
image = channel_page.asarray()
scaling_type = channel_page.tags["33027"].value
if scaling_type == "LinearScaling":
scaling = channel_page.tags["33028"].value
offset = channel_page.tags["33029"].value
image = (image * scaling) + offset
elif scaling_type == "NullScaling":
pass
else:
raise ValueError(f"Scaling type {scaling_type} is not 'NullScaling' or 'LinearScaling'")
# Get page for common metadata between scans
metadata_page = tif.pages[0]
return (image * 1e9, _jpk_pixel_to_nm_scaling(metadata_page))
|