Skip to content

Commit

Permalink
fix: do not modify preprocessing options when applying them
Browse files Browse the repository at this point in the history
  • Loading branch information
paulmueller committed Aug 16, 2021
1 parent b2ed54b commit e89a20b
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 23 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
3.1.1
- fix: do not modify preprocessing options when applying them (create
a copy of the dictionary)
- ref: remove `Indentation.reset` in favor of `AFMData.reset_data`
3.1.0
- feat: new contact point estimation method "fit_constant_polynomial"
which applies a piece-wise constant and polynomial fit
Expand Down
18 changes: 3 additions & 15 deletions nanite/indent.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from collections import OrderedDict
import copy
import inspect
import warnings

import afmformats
Expand Down Expand Up @@ -33,14 +32,6 @@ def __init__(self, data, metadata, diskcache=None):
# Curve rating (see `self.rate_quality`)
self._rating = None

# Store initial parameters for reset (see `self.reset`)
frame = inspect.currentframe()
iargs, _, _, values = inspect.getargvalues(frame)
self._init_kwargs = {
"data": copy.deepcopy(data),
"metadata": copy.deepcopy(metadata)
}

@property
def data(self):
warnings.warn("Please use __getitem__ instead!", DeprecationWarning)
Expand Down Expand Up @@ -91,9 +82,10 @@ def apply_preprocessing(self, preprocessing=None, options=None,
fp = self.fit_properties
fp["preprocessing"] = preprocessing
fp["preprocessing_options"] = options
# Reset all data
self.reset()
# Reset rating
self._rating = None
# Apply preprocessing
# (This will call `AFMData.reset_data` on self)
details = IndentationPreprocessor.apply(apret=self,
identifiers=preprocessing,
options=options,
Expand Down Expand Up @@ -380,7 +372,3 @@ def rate_quality(self, regressor="Extra Trees", training_set="zef18",
# Use cached rating
rt = self._rating[-1]
return rt

def reset(self):
"""Resets all data operations"""
self.__init__(**self._init_kwargs)
11 changes: 3 additions & 8 deletions nanite/preproc.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,6 @@ def apply(apret, identifiers=None, options=None, ret_details=False,
Return preprocessing details dictionary
preproc_names: list
Deprecated - use `identifiers` instead
Notes
-----
This method is usually called from within the `Indentation`
class instance. If you are using this class directly and
apply it more than once, you might need to call
`apret.reset()` before preprocessing a second time.
"""
if preproc_names is not None:
identifiers = preproc_names
Expand All @@ -103,7 +96,9 @@ class instance. If you are using this class directly and
if req is not None and ((set(req) & set(act)) != set(req)):
raise ValueError(f"The preprocessing step '{pid}' requires"
f" the steps {meth.steps_required}!")
kwargs = options.get(pid, {}) # empty dict if not defined
# create a copy of the dictionary (if it exists) so that
# `ret_details` is not written to it
kwargs = copy.deepcopy(options.get(pid, {}))
if "ret_details" in inspect.signature(meth).parameters:
# only set `ret_details` if method accepts it
kwargs["ret_details"] = ret_details
Expand Down
57 changes: 57 additions & 0 deletions tests/test_indent.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,63 @@ def test_get_model():
assert md2 is md


def test_preprocessing_reset():
fd = nanite.IndentationGroup(jpkfile)[0]
fd.apply_preprocessing(["compute_tip_position",
"correct_force_offset",
"correct_tip_offset"],
options={"correct_tip_offset": {
"method": "fit_constant_line"}})

inparams = nanite.model.model_hertz_paraboloidal.get_parameter_defaults()
inparams["baseline"].vary = True
inparams["contact_point"].set(1.8e-5)

# Perform fit and make sure that all properties are set
fd.fit_model(model_key="hertz_para",
params_initial=inparams,
range_x=(0, 0),
range_type="absolute",
x_axis="tip position",
y_axis="force",
segment="approach",
weight_cp=False)
fd.rate_quality(training_set="zef18",
regressor="Extra Trees")
assert fd._rating is not None
assert fd.preprocessing == ["compute_tip_position",
"correct_force_offset",
"correct_tip_offset"]
assert fd.preprocessing_options == {"correct_tip_offset": {
"method": "fit_constant_line"}}
assert not fd._preprocessing_details
assert np.allclose(
fd._fit_properties["params_fitted"]["contact_point"].value,
-3.5147555568064786e-06,
atol=0)
assert "tip position" in fd

# Change preprocessing and make sure properties are reset
fd.apply_preprocessing(["compute_tip_position",
"correct_force_offset",
"correct_tip_offset"],
options={"correct_tip_offset": {
"method": "fit_constant_polynomial"}})
assert fd._rating is None
assert fd.preprocessing == ["compute_tip_position",
"correct_force_offset",
"correct_tip_offset"]
assert fd.preprocessing_options == {"correct_tip_offset": {
"method": "fit_constant_polynomial"}}
assert not fd._preprocessing_details
assert "params_fitted" not in fd._fit_properties
assert "tip position" in fd

# Change preprocessing, removing tip position
fd.apply_preprocessing(["correct_force_offset"])
assert "tip position" not in fd


def test_rate_quality_cache():
ds1 = nanite.IndentationGroup(jpkfile)
idnt = ds1[0]
Expand Down

0 comments on commit e89a20b

Please sign in to comment.