From 60edbd9184b33e852a599c9830033e25ce30494a Mon Sep 17 00:00:00 2001 From: Johannes Mueller Date: Thu, 12 Dec 2024 15:07:26 +0100 Subject: [PATCH] Fix unnecessary and harmful copy of pandas objects Inheritants of `PyLifeSignal` generally need not implement `.__init__()` `PyLifeSinal` calls `.validate()`. Signed-off-by: Johannes Mueller --- CHANGELOG.md | 9 ++++-- src/pylife/materiallaws/woehlercurve.py | 4 --- src/pylife/strength/woehler_fkm_nonlinear.py | 15 +++------- tests/materiallaws/test_woehlercurve.py | 16 +++++++++++ tests/strength/test_woehler_fkm_nonlinear.py | 29 ++++++++++++++++++++ 5 files changed, 56 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2175aea9..1d4323d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,12 +11,17 @@ In this file noteworthy changes of new releases of pyLife are documented since * Drop support for python-3.8 ast it is end of life -### Minor improvments +### Minor improvements -* Connectivity information is now transfered from odbserver to odbclient as +* Connectivity information is now transferred from odbserver to odbclient as ints. +### Bugfixes + +* Fix unnecessary and harmful copy of pandas object in Wöhler classes (#146) + + ## pylife-2.1.3 ### Improvements diff --git a/src/pylife/materiallaws/woehlercurve.py b/src/pylife/materiallaws/woehlercurve.py index b77cf3b3..0d3c1cf1 100644 --- a/src/pylife/materiallaws/woehlercurve.py +++ b/src/pylife/materiallaws/woehlercurve.py @@ -52,10 +52,6 @@ class WoehlerCurve(PylifeSignal): or calculated from ``TN`` if given. """ - def __init__(self, pandas_obj): - self._obj = pandas_obj.copy() - self._validate() - def _validate(self): self.fail_if_key_missing(['k_1', 'ND', 'SD']) self._k_2 = self._obj.get('k_2', np.inf) diff --git a/src/pylife/strength/woehler_fkm_nonlinear.py b/src/pylife/strength/woehler_fkm_nonlinear.py index 33bc46f3..64fab37c 100644 --- a/src/pylife/strength/woehler_fkm_nonlinear.py +++ b/src/pylife/strength/woehler_fkm_nonlinear.py @@ -46,10 +46,6 @@ class WoehlerCurvePRAM(PylifeSignal): * ``P_RAM_D`` : The damage parameter value of the endurance limit of the component, computed as P_RAM_D_WS / f_RAM (FKM nonlinear, eq. 2.6-89) """ - def __init__(self, pandas_obj): - self._obj = pandas_obj.copy() - self._validate() - def _validate(self): self.fail_if_key_missing(['P_RAM_Z', 'P_RAM_D', 'd_1', 'd_2']) @@ -195,13 +191,6 @@ class WoehlerCurvePRAJ(PylifeSignal): * ``P_RAJ_D_0`` : The initial load level of the endurance limit """ - def __init__(self, pandas_obj): - self._obj = pandas_obj.copy() - self._validate() - - # eq. (2.9-27) - self._P_RAJ_D = self._obj.P_RAJ_D_0 - def _validate(self): self.fail_if_key_missing(['P_RAJ_Z', 'P_RAJ_D_0', 'd_RAJ']) @@ -212,6 +201,10 @@ def _validate(self): if self._obj.d_RAJ >= 0: raise ValueError(f"d_RAJ ({self._obj.d_RAJ}) has to be negative!") + # eq. (2.9-27) + self._P_RAJ_D = self._obj.P_RAJ_D_0 + + def update_P_RAJ_D(self, P_RAJ_D): """This method is used to update the fatigue strength P_RAJ_D, which is stored in this woehler curve. diff --git a/tests/materiallaws/test_woehlercurve.py b/tests/materiallaws/test_woehlercurve.py index 34916894..8a2f764c 100644 --- a/tests/materiallaws/test_woehlercurve.py +++ b/tests/materiallaws/test_woehlercurve.py @@ -550,3 +550,19 @@ def test_load_is_basquin_load(SD, k_1, ND, cycles): def test_cycles_is_basquin_cycles(SD, k_1, ND, load): wc = WoehlerCurve.from_parameters(SD=SD, k_1=k_1, ND=ND) assert wc.cycles(load) == wc.basquin_cycles(load) + + +def test_changed_TN(): + wc = pd.Series({ + 'k_1': 7., + 'TN': 1.75, + 'ND': 1e6, + 'SD': 300.0 + }) + + _ = wc.woehler + + wc['TN'] = 1.48 + new_wc = wc.woehler.to_pandas() + + assert new_wc['TN'] == 1.48 diff --git a/tests/strength/test_woehler_fkm_nonlinear.py b/tests/strength/test_woehler_fkm_nonlinear.py index 57eb3788..e36e8e71 100644 --- a/tests/strength/test_woehler_fkm_nonlinear.py +++ b/tests/strength/test_woehler_fkm_nonlinear.py @@ -151,6 +151,21 @@ def test_woehler_curve_P_RAM_exceptions(P_RAM_Z, P_RAM_D, d_1, d_2): component_woehler_curve_P_RAM = assessment_parameters.woehler_P_RAM +def test_woehler_curve_P_RAM_change_params(): + ap = pd.Series({ + "P_RAM_Z": 400.0, + "P_RAM_D": 150.0, + "d_1": -0.3, + "d_2": -0.2 + }) + + _ = ap.woehler_P_RAM + + ap["d_2"] = -0.9 + + assert ap.woehler_P_RAM.to_pandas()["d_2"] == -0.9 + + # ---------- P_RAJ -------------- @pytest.mark.parametrize( "P_RAJ_Z, P_RAJ_D_0, d_RAJ", [ @@ -260,3 +275,17 @@ def test_woehler_curve_P_RAJ_exceptions(P_RAJ_Z, P_RAJ_D_0, d_RAJ): with pytest.raises(ValueError, match="has to be"): component_woehler_curve_P_RAJ = assessment_parameters.woehler_P_RAJ + + +def test_woehler_curve_P_RAJ_change_params(): + ap = pd.Series({ + "P_RAJ_Z": 150.0, + "P_RAJ_D_0": 0.1, + "d_RAJ": -0.5, + }) + + _ = ap.woehler_P_RAJ + + ap["d_RAJ"] = -0.7 + + assert ap.woehler_P_RAJ.to_pandas()["d_RAJ"] == -0.7