Skip to content

Commit

Permalink
fix: spatial smoothing not working in some cases (close #15)
Browse files Browse the repository at this point in the history
  • Loading branch information
paulmueller committed Aug 16, 2021
1 parent 90cafaf commit 8330318
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 29 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
- feat: contact point estimation methods now return detailed
information about the procedure (currently plottable data to
understand the process)
- fix: spatial smoothing not working in some cases (#15)
- ref: remove "...smoothed" column data (which was never used anyway);
instead, apply smoothing directly to AFMData subclass
- setup: bump afmformats from 0.16.0 to 0.16.3
3.0.0
- BREAKING CHANGE: The contact point estimation method "scheme_2020"
has been removed, although it has been the default for some time.
Expand Down
2 changes: 1 addition & 1 deletion nanite/indent.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def __init__(self, data, metadata, diskcache=None):

@property
def data(self):
warnings.warn("Please use __getitem__ instead!")
warnings.warn("Please use __getitem__ instead!", DeprecationWarning)
return self

@property
Expand Down
37 changes: 13 additions & 24 deletions nanite/preproc.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,38 +276,27 @@ def correct_split_approach_retract(apret):

@staticmethod
@preprocessing_step(identifier="smooth_height",
name="spatial smoothing")
name="monotonic height data")
def smooth_height(apret):
"""Smoothen height data
"""Make height data monotonic
For the columns "height (measured)" and "tip position",
and for the approach and retract data separately, this
method adds the columns "height (measured, smoothed)" and
"tip position (smoothed)" to `apret`.
For the columns "height (measured)", "height (piezo), and
"tip position", this method ensures that the approach and
retract segments are monotonic.
"""
orig = ["height (measured)",
"height (piezo)",
"tip position"]
dest = ["height (measured, smoothed)",
"tip position (smoothed)"]
for o, d in zip(orig, dest):
if o not in apret.columns:
for col in orig:
if col not in apret.columns:
continue
# Get approach and retract data
app_idx = apret["segment"] == 0
app = np.array(apret[o][app_idx])
ret_idx = apret["segment"] == np.max(apret["segment"])
ret = np.array(apret[o][ret_idx])
# Apply smoothing
sm_app = smooth_axis_monotone(app)
sm_ret = smooth_axis_monotone(ret)
sm_app = smooth_axis_monotone(apret.appr[col])
sm_ret = smooth_axis_monotone(apret.retr[col])

# Make sure that approach always comes before retract
begin = np.where(app_idx)[0]
end = np.where(ret_idx)[0]
assert(np.all(end-begin > 0)), "Found retract before approach!"

# If everything is ok, we can add the new columns
apret[d] = np.concatenate((sm_app, sm_ret))
# Replace the column data
apret.appr[col] = sm_app
apret.retr[col] = sm_ret


#: Available preprocessors
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
license="GPL v3",
description=description,
long_description=open('README.rst').read() if exists('README.rst') else '',
install_requires=["afmformats>=0.16.0",
install_requires=["afmformats>=0.16.3",
"h5py>=2.8.0",
"lmfit>=1",
"numpy>=1.16.0", # cython build
Expand Down
10 changes: 7 additions & 3 deletions tests/test_indent2.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,17 @@
def test_app_ret():
grp = IndentationGroup(jpkfile)
idnt = grp[0]
idnt.apply_preprocessing(["compute_tip_position"])
height = np.array(idnt["height (measured)"], copy=True)
tip_position = np.array(idnt["tip position"], copy=True)
idnt.apply_preprocessing(["smooth_height"])
hms = np.array(idnt["height (measured, smoothed)"])
hms = np.array(idnt["height (measured)"])
assert not np.all(height == hms)
idnt.apply_preprocessing(["compute_tip_position",
"smooth_height"])
hms2 = np.array(idnt["height (measured, smoothed)"])
hms2 = np.array(idnt["height (measured)"])
assert np.all(hms == hms2)
np.array(idnt["tip position (smoothed)"])
assert not np.all(idnt["tip position"] == tip_position)


def test_tip_sample_separation():
Expand Down
18 changes: 18 additions & 0 deletions tests/test_preproc.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Test preprocessing"""
import pathlib

import numpy as np
import pytest

from nanite import IndentationGroup
Expand Down Expand Up @@ -57,6 +58,23 @@ def test_process_bad():
idnt.fit_model()


@pytest.mark.filterwarnings(
'ignore::nanite.smooth.DoubledSmoothingWindowWarning:')
def test_smooth():
idnt = IndentationGroup(data_path / "spot3-0192.jpk-force")[0]
idnt.apply_preprocessing(["compute_tip_position",
"correct_force_offset",
"correct_tip_offset"])
orig = np.array(idnt["tip position"], copy=True)
# now apply smoothing filter
idnt.apply_preprocessing(["compute_tip_position",
"correct_force_offset",
"correct_tip_offset",
"smooth_height"])
new = np.array(idnt["tip position"], copy=True)
assert not np.all(orig == new)


def test_unknown_method():
idnt = IndentationGroup(data_path / "spot3-0192.jpk-force")[0]
with pytest.raises(KeyError, match="unknown_method"):
Expand Down

0 comments on commit 8330318

Please sign in to comment.