From 6caaaf0f9ca6dc2ba84c5ebbef006b937c323ef5 Mon Sep 17 00:00:00 2001 From: reneeotten Date: Sat, 29 May 2021 11:36:45 -0400 Subject: [PATCH] ENH/FIX: coerce 'data' and 'independent_var' in Model class - input 'data' will always become 'float64' or 'complex128' - coercion is only done for certain data types in case of an 'independent_var' to still allow for more complicated (user-defined) data types See: #723 Closes: #727 --- doc/whatsnew.rst | 1 + lmfit/model.py | 31 ++++++++++++++++++++----------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/doc/whatsnew.rst b/doc/whatsnew.rst index ff6d37491..9e21e5c94 100644 --- a/doc/whatsnew.rst +++ b/doc/whatsnew.rst @@ -22,6 +22,7 @@ New features: Bug fixes/enhancements: - do not overwrite user-specified figure titles in Model.plot() functions and allow setting with 'title' keyword argument (PR #711) - preserve Parameters subclass in deepcopy (@jenshnielsen; PR #719) +- coerce ``data`` and ``indepdent_vars`` to NumPy array with ``dtype=float64`` whenever applicable (Issues #723 and #727) Various: - update asteval dependency to >=0.9.22 to avoid DeprecationWarnings from NumPy v1.20.0 (PR #707) diff --git a/lmfit/model.py b/lmfit/model.py index f36fe3957..ce301921c 100644 --- a/lmfit/model.py +++ b/lmfit/model.py @@ -982,15 +982,6 @@ def fit(self, data, params=None, weights=None, method='leastsq', msg += 'Non initialized parameters: %s' % str(blank) raise ValueError(msg) - # Do not alter anything that implements the array interface (np.array, pd.Series) - # but convert other iterables (e.g., Python lists) to NumPy arrays. - if not hasattr(data, '__array__'): - data = np.asfarray(data) - for var in self.independent_vars: - var_data = kwargs[var] - if isinstance(var_data, (list, tuple)): - kwargs[var] = np.asfarray(var_data) - # Handle null/missing values. if nan_policy is not None: self.nan_policy = nan_policy @@ -1005,12 +996,30 @@ def fit(self, data, params=None, weights=None, method='leastsq', # If independent_vars and data are alignable (pandas), align them, # and apply the mask from above if there is one. - for var in self.independent_vars: if not np.isscalar(kwargs[var]): - # print("Model fit align ind dep ", var, mask.sum()) kwargs[var] = _align(kwargs[var], mask, data) + # Make sure `dtype` for data is always `float64` or `complex128` + if np.isrealobj(data): + data = np.asfarray(data) + elif np.iscomplexobj(data): + data = np.asarray(data, dtype='complex128') + + # Coerce `dtype` for independent variable(s) to `float64` or + # `complex128` when the variable has one of the following types: list, + # tuple, numpy.ndarray, or pandas.Series + for var in self.independent_vars: + var_data = kwargs[var] + if isinstance(var_data, (list, tuple)): + kwargs[var] = np.asfarray(var_data) + elif (isinstance(var_data, (np.ndarray, Series)) and + np.isrealobj(var_data)): + kwargs[var] = np.asfarray(var_data) + elif (isinstance(var_data, (np.ndarray, Series)) and + np.iscomplexobj(var_data)): + kwargs[var] = np.asarray(var_data, dtype='complex128') + if fit_kws is None: fit_kws = {}