tests(jpk): Adds sample .jpk-qi-image to test suite#155
Conversation
Closes #154 AFMReader appears to already be able to read files with `.jpk-qi-image` as the `AFMReader.jpk.load_jpk()` function loads these fine. @sebastienjanel provided a sample file so its been added to the test suite and parameterised tests for the following channels created... - `measuredHeight_trace` - `vDeflection_trace` - `adhesion_trace` - `height_trace` - `slope_trace`
|
The two important channels for TopoStats are "Height measured" and "Contact Point Offset". The measured height comes directly along with the QI file in a separate image, and the contact point offset is computed from the force curves (zero-force topography). |
You can access the "Height Measured" channel from the standard image by using |
|
When I loaded the image the channels I listed above were the only ones available which is why I've only been able to add tests for those. NB the file is in from pathlib import Path
from AFMReader.jpk import load_jpk
BASE_DIR = Path.cwd()
JPK_DIR = BASE_DIR / "jpk-qi"
file = "2025.05.20-17.48.42.479.jpk-qi-image"
jpk_file = load_jpk(file_path=JPK_DIR / file, channel="Height (measured)")
14:43:29 | INFO |jpk.py:jpk:load_jpk:213 | Loading image from : /home/neil/work/git/hub/AFM-SPM/AFMReader/tmp/jpk-qi/2025.05.20-17.48.42.479.jpk-qi-image
14:43:29 | INFO |jpk.py:jpk:_load_jpk_tags:274 | Configuration loaded from : /home/neil/.virtualenvs/topostats-afmreader/lib/python3.11/site-packages/AFMReader/default_config.yaml
14:43:29 | ERROR |jpk.py:jpk:load_jpk:234 | 'Height (measured)' not in .jpk-qi-image channel list: {'measuredHeight_trace': 3, 'vDeflection_trace': 2, 'adhesion_trace': 4, 'height_trace': 5, 'slope_trace': 6}
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
File ~/.virtualenvs/topostats-afmreader/lib/python3.11/site-packages/AFMReader/jpk.py:232, in load_jpk(file_path, channel, config_path, flip_image)
231 try:
--> 232 channel_idx = channel_list[channel]
233 except KeyError as e:
KeyError: 'Height (measured)'
The above exception was the direct cause of the following exception:
ValueError Traceback (most recent call last)
Cell In[11], line 1
----> 1 jpk_file = load_jpk(file_path=JPK_DIR / file, channel="Height (measured)")
File ~/.virtualenvs/topostats-afmreader/lib/python3.11/site-packages/AFMReader/jpk.py:235, in load_jpk(file_path, channel, config_path, flip_image)
233 except KeyError as e:
234 logger.error(f"'{channel}' not in {file_path.suffix} channel list: {channel_list}")
--> 235 raise ValueError(f"'{channel}' not in {file_path.suffix} channel list: {channel_list}") from e
237 # Get image and if applicable, scale it
238 channel_page = tif.pages[channel_idx]
ValueError: 'Height (measured)' not in .jpk-qi-image channel list: {'measuredHeight_trace': 3, 'vDeflection_trace': 2, 'adhesion_trace': 4, 'height_trace': 5, 'slope_trace': 6}The channels that are reported as being present are work fine though... jpk_file = load_jpk(file_path=JPK_DIR / file, channel="measuredHeight_trace")
14:45:33 | INFO |jpk.py:jpk:load_jpk:213 | Loading image from : /home/neil/work/git/hub/AFM-SPM/AFMReader/tmp/jpk-qi/2025.05.20-17.48.42.479.jpk-qi-image
14:45:34 | INFO |jpk.py:jpk:_load_jpk_tags:274 | Configuration loaded from : /home/neil/.virtualenvs/topostats-afmreader/lib/python3.11/site-packages/AFMReader/default_config.yaml
14:45:34 | INFO |jpk.py:jpk:load_jpk:251 | [2025.05.20-17.48.42.479] : Extracted image.
jpk_file = load_jpk(file_path=JPK_DIR / file, channel="vDeflection_trace")
14:45:34 | INFO |jpk.py:jpk:load_jpk:213 | Loading image from : /home/neil/work/git/hub/AFM-SPM/AFMReader/tmp/jpk-qi/2025.05.20-17.48.42.479.jpk-qi-image
14:45:34 | INFO |jpk.py:jpk:_load_jpk_tags:274 | Configuration loaded from : /home/neil/.virtualenvs/topostats-afmreader/lib/python3.11/site-packages/AFMReader/default_config.yaml
14:45:34 | INFO |jpk.py:jpk:load_jpk:251 | [2025.05.20-17.48.42.479] : Extracted image.
jpk_file = load_jpk(file_path=JPK_DIR / file, channel="adhesion_trace")
14:45:34 | INFO |jpk.py:jpk:load_jpk:213 | Loading image from : /home/neil/work/git/hub/AFM-SPM/AFMReader/tmp/jpk-qi/2025.05.20-17.48.42.479.jpk-qi-image
14:45:34 | INFO |jpk.py:jpk:_load_jpk_tags:274 | Configuration loaded from : /home/neil/.virtualenvs/topostats-afmreader/lib/python3.11/site-packages/AFMReader/default_config.yaml
14:45:34 | INFO |jpk.py:jpk:load_jpk:251 | [2025.05.20-17.48.42.479] : Extracted image.
jpk_file = load_jpk(file_path=JPK_DIR / file, channel="height_trace")
14:45:34 | INFO |jpk.py:jpk:load_jpk:213 | Loading image from : /home/neil/work/git/hub/AFM-SPM/AFMReader/tmp/jpk-qi/2025.05.20-17.48.42.479.jpk-qi-image
14:45:34 | INFO |jpk.py:jpk:_load_jpk_tags:274 | Configuration loaded from : /home/neil/.virtualenvs/topostats-afmreader/lib/python3.11/site-packages/AFMReader/default_config.yaml
14:45:34 | INFO |jpk.py:jpk:load_jpk:251 | [2025.05.20-17.48.42.479] : Extracted image.
jpk_file = load_jpk(file_path=JPK_DIR / file, channel="slope_trace")
14:45:34 | INFO |jpk.py:jpk:load_jpk:213 | Loading image from : /home/neil/work/git/hub/AFM-SPM/AFMReader/tmp/jpk-qi/2025.05.20-17.48.42.479.jpk-qi-image
14:45:34 | INFO |jpk.py:jpk:_load_jpk_tags:274 | Configuration loaded from : /home/neil/.virtualenvs/topostats-afmreader/lib/python3.11/site-packages/AFMReader/default_config.yaml
14:45:34 | INFO |jpk.py:jpk:load_jpk:251 | [2025.05.20-17.48.42.479] : Extracted image.The |
Tests were failing, hopefully this fixes that by using `pytest.approx()`.
|
That's because these channels come from 2 different kind of files. @derollins is right in the channel names. But i must also add that in some situation JPK DP write the contact point topography as "contact point", not "contact point offset". These are channel 3 and 5. |
|
Thanks, @sebastienjanel . Like in all AFM files, the channel content will depend on which channels you choose to save (or export from JPK DP). AFMreader provides an error message with the list of available channels if the one inputted isn't discovered. It doesn't necessarily matter what they are called and each manufacture and even instrument have different names for channels. As long as you discover the name of the channel you are looking for you should be able to load it with AFMReader. |
|
Sounds as though this could be very open-ended with regards to channels! |
Closes #154
AFMReader appears to already be able to read files with
.jpk-qi-imageas theAFMReader.jpk.load_jpk()function loads these fine.@sebastienjanel provided a sample file so its been added to the test suite and parameterised tests for the following channels created...
measuredHeight_tracevDeflection_traceadhesion_traceheight_traceslope_trace