Skip to content

Commit

Permalink
ref: sneak in sensitivity and spring constant at a lower level
Browse files Browse the repository at this point in the history
  • Loading branch information
paulmueller committed Sep 29, 2023
1 parent d2d9761 commit 480d1ab
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 8 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
pip freeze
- name: Lint with flake8
run: |
flake8 --exclude _version .
flake8 --exclude _version.py .
- name: Test with pytest
run: |
coverage run --source=afmformats -m pytest tests
Expand Down
38 changes: 31 additions & 7 deletions afmformats/formats/fmt_jpk/jpk_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

from . import jpk_data, jpk_meta


__all__ = ["ArchiveCache", "JPKReader"]


Expand Down Expand Up @@ -180,6 +179,33 @@ def _get_index_segment_properties(self, index, segment):
else:
if np.isnan(prop[p]):
prop.pop(p)

# 6. sneakily insert spring constant and sensitivity into the property
# lists. This is manipulation of metadata at the lowest possible
# level. We need it in :func:`jpk_data.load_dat_unit` as well
# as in :func:`.get_metadata`.
prmet = jpk_meta.get_primary_meta_recipe()
for key, base_slot, unit in [
("spring constant", "distance", "N"),
("sensitivity", "volts", "m")]:
if key in self._user_metadata:
for opt_mult in prmet[key]:
# channel.vDeflection.conversion-set.conversion.
# distance.scaling.multiplier
prop[opt_mult] = self._user_metadata[key]
# channel.vDeflection.conversion-set.conversion.
# distance.scaling.offset
opt_off = opt_mult.rsplit(".", 1)[0] + ".offset"
prop[opt_off] = 0
# channel.vDeflection.conversion-set.conversion.
# distance.scaling.unit
opt_unit = opt_mult.rsplit(".", 1)[0] + ".unit"
prop[opt_unit] = unit
# channel.vDeflection.conversion-set.conversion.
# distance.base-calibration-slot
opt_slot = (opt_mult.rsplit(".", 2)[0]
+ ".base-calibration-slot")
prop[opt_slot] = base_slot
return prop

def get_data(self, column, index, segment=None):
Expand Down Expand Up @@ -331,14 +357,11 @@ def get_metadata(self, index, segment=None):
md.update(mdap)
return md

# 1. Populate with primary metadata
# 1. Populate with primary metadata. Note that we already manipulated
# the user-defined sensitivity and spring constant metadata in
# the property list in :func:`._get_index_segment_properties`
md = self.get_metadata_jpk_primary(index=index, segment=segment)

# Make sure that spring constant and sensitivity are in the metadata,
# otherwise fail. We also need those two for computations further
# below.
md.update(self._user_metadata)

keys_required = ["spring constant", "sensitivity"]
keys_missing = [k for k in keys_required if k not in md]

Expand Down Expand Up @@ -457,3 +480,4 @@ def set_metadata(self, metadata):
self._user_metadata.clear()
self._user_metadata.update(metadata)
self.get_metadata.cache_clear()
self._get_index_segment_properties.cache_clear()
21 changes: 21 additions & 0 deletions tests/test_fmt_jpk_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,27 @@ def test_load_jpk_map():
assert ds.metadata["session id"] == ds2.metadata["session id"]


def test_load_jpk_map_modify_metadata():
jpkfile = data_path / "fmt-jpk-fd_map2x2_extracted.jpk-force-map"

# initial values
ds = afmformats.load_data(path=jpkfile)[2]
init_force = -5.8540192943834714e-10
assert np.allclose(ds["force"][0], init_force)
old_spring_constant = ds.metadata["spring constant"]
new_spring_constant = 10
assert not np.allclose(old_spring_constant,
new_spring_constant), "sanity check"

# load it again, this time with new metadata
# (the spring constant is proportional to the force and there is no offset)
ds2 = afmformats.load_data(path=jpkfile,
meta_override={
"spring constant": new_spring_constant})[2]
new_force = init_force / old_spring_constant * new_spring_constant
assert np.allclose(ds2["force"][0], new_force)


def test_load_jpk_simple():
jpkfile = data_path / "fmt-jpk-fd_spot3-0192.jpk-force"
afmlist = afmformats.load_data(path=jpkfile)
Expand Down
9 changes: 9 additions & 0 deletions tests/test_fmt_jpk_single.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,3 +157,12 @@ def test_load_jpk():
assert md["imaging mode"] == "force-distance"
assert len(jpkr) == 1, "Only one measurement"
assert len(jpkr.get_index_segment_numbers(0)) == 2, "approach and retract"


def test_load_jpk_with_own_metadata():
jpkfile = data_path / "fmt-jpk-fd_single-modified_2023.jpk-force"
data = afmformats.load_data(jpkfile,
meta_override={"spring constant": 10,
"sensitivity": .05})
apret = data[0]
assert np.allclose(apret["force"][0], -0.2454449015321114)

0 comments on commit 480d1ab

Please sign in to comment.