"""Tools to transform NaN in numpy arrays in order to be serializedMichel BierlaireMon May 19 2025, 11:57:38"""importnumpyasnp
[docs]defsafe_serialize_array(array:np.ndarray,)->list[float|None]|list[list[float|None]]:""" Convert a NumPy array with potential NaN values into a nested or flat list with `None` in place of `np.nan`, making it safe for YAML or JSON serialization. :param array: A NumPy array that may contain np.nan values. :return: A list (1D or 2D) with None in place of np.nan, suitable for serialization. """ifnotisinstance(array,np.ndarray):raiseTypeError(f'Input must be a NumPy array, not {type(array)}.')ifarray.ndim==1:return[Noneifnp.isnan(val)elsefloat(val)forvalinarray]elifarray.ndim==2:return[[Noneifnp.isnan(val)elsefloat(val)forvalinrow]forrowinarray]else:raiseValueError("Only 1D and 2D arrays are supported.")
[docs]defsafe_deserialize_array(serialized:list[float|None]|list[list[float|None]],)->list[float]|list[list[float]]:""" Convert a flat or nested list with None values (as parsed from YAML or JSON) into a list with None replaced by float('nan'). :param serialized: A list (1D or 2D) containing float or None values. :return: A list (1D or 2D) with None replaced by float('nan'). """ifnotisinstance(serialized,list):raiseTypeError("Input must be a list.")ifall(isinstance(val,(float,int,type(None)))forvalinserialized):# 1D casereturn[float('nan')ifvalisNoneelsefloat(val)forvalinserialized]elifall(isinstance(row,list)andall(isinstance(val,(float,int,type(None)))forvalinrow)forrowinserialized):# 2D casereturn[[float('nan')ifvalisNoneelsefloat(val)forvalinrow]forrowinserialized]else:raiseTypeError("Input must be a 1D or 2D list of numbers or None.")