From 81f3dd90b4c65e69c532a5b8ebab43c825576b61 Mon Sep 17 00:00:00 2001 From: Pol Febrer Calabozo Date: Thu, 12 Mar 2026 18:08:02 +0100 Subject: [PATCH 1/3] Fix plots bug due to new pandas casting --- src/sisl/viz/plotters/xarray.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/sisl/viz/plotters/xarray.py b/src/sisl/viz/plotters/xarray.py index 81190fb7a..82e62cb2d 100644 --- a/src/sisl/viz/plotters/xarray.py +++ b/src/sisl/viz/plotters/xarray.py @@ -9,6 +9,7 @@ import numpy as np from xarray import DataArray, Dataset +import pandas as pd from . import plot_actions @@ -461,6 +462,25 @@ def _draw_xarray_lines( "border_width", "border_color", ) + + for key, value in style.items(): + value = style[key] + + # xarray uses pandas for casting types, and pandas decided to change + # the default behavior and parse [None, ""], to [nan, ""]. Passing + # NaN to plotting functions when they are expecting None breaks things. + # Here we make sure that we parse all NaN to None + # Pandas docs on this: + # https://pandas.pydata.org/docs/user_guide/migration-3-strings.html + old_infer_string = pd.options.future.infer_string + pd.options.future.infer_string = False + try: + style[key] = value.where(value.notnull(), other=None) + except: + pass + finally: + pd.options.future.infer_string = old_infer_string + for key in style_keys: lines_style[key] = style.get(key) From b6807bdc9f13144b09a23148ac4fae1175be9013 Mon Sep 17 00:00:00 2001 From: Nick Papior Date: Fri, 13 Mar 2026 10:14:34 +0100 Subject: [PATCH 2/3] refactor of code for older pandas versions --- changes/983.fix.rst | 1 + src/sisl/viz/plotters/xarray.py | 55 +++++++++++++++++++++------------ 2 files changed, 37 insertions(+), 19 deletions(-) create mode 100644 changes/983.fix.rst diff --git a/changes/983.fix.rst b/changes/983.fix.rst new file mode 100644 index 000000000..0fc5f291a --- /dev/null +++ b/changes/983.fix.rst @@ -0,0 +1 @@ +bug fix for pandas >= 3 migration diff --git a/src/sisl/viz/plotters/xarray.py b/src/sisl/viz/plotters/xarray.py index 82e62cb2d..45662efbb 100644 --- a/src/sisl/viz/plotters/xarray.py +++ b/src/sisl/viz/plotters/xarray.py @@ -8,14 +8,48 @@ from typing import Literal, Optional, Union import numpy as np -from xarray import DataArray, Dataset import pandas as pd +from xarray import DataArray, Dataset from . import plot_actions # from sisl.viz.nodes.processors.grid import get_isos +def _correct_pandas_string_none(dic: dict[str, DataArray]): + """Correct string arguments in xarray arrays to avoid casting to nan + + This is a migration notice from pandas >= 3. + They change their str implementation to a custom (new default) dtype. + And the result is that `None` will be parsed to `np.nan` as opposed + to the old `None -> None` parsing. + """ + + # xarray uses pandas for casting types, and pandas decided to change + # the default behavior and parse [None, ""], to [nan, ""]. Passing + # NaN to plotting functions when they are expecting None breaks things. + # Here we make sure that we parse all NaN to None + # Pandas docs on this: + # https://pandas.pydata.org/docs/user_guide/migration-3-strings.html + old_infer_string = pd.options.future.infer_string + pd.options.future.infer_string = False + + for key, value in dic.items(): + value = dic[key] + try: + dic[key] = value.where(value.notnull(), other=None) + except: + pass + + pd.options.future.infer_string = old_infer_string + + +if int(pd.__version__.split(",")[0]) >= 3: + + def _correct_pandas_string_none(dic: dict[str, str]): + pass + + def _process_xarray_data( data: Union[DataArray, Dataset], x: Union[str, None] = None, @@ -462,24 +496,7 @@ def _draw_xarray_lines( "border_width", "border_color", ) - - for key, value in style.items(): - value = style[key] - - # xarray uses pandas for casting types, and pandas decided to change - # the default behavior and parse [None, ""], to [nan, ""]. Passing - # NaN to plotting functions when they are expecting None breaks things. - # Here we make sure that we parse all NaN to None - # Pandas docs on this: - # https://pandas.pydata.org/docs/user_guide/migration-3-strings.html - old_infer_string = pd.options.future.infer_string - pd.options.future.infer_string = False - try: - style[key] = value.where(value.notnull(), other=None) - except: - pass - finally: - pd.options.future.infer_string = old_infer_string + _correct_pandas_string_none(style) for key in style_keys: lines_style[key] = style.get(key) From fbcffc7002b7b215ff913e6caa0a31cbc2d90ef2 Mon Sep 17 00:00:00 2001 From: Nick Papior Date: Fri, 13 Mar 2026 10:23:39 +0100 Subject: [PATCH 3/3] error --- src/sisl/viz/plotters/xarray.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sisl/viz/plotters/xarray.py b/src/sisl/viz/plotters/xarray.py index 45662efbb..2ba1a3e86 100644 --- a/src/sisl/viz/plotters/xarray.py +++ b/src/sisl/viz/plotters/xarray.py @@ -44,7 +44,7 @@ def _correct_pandas_string_none(dic: dict[str, DataArray]): pd.options.future.infer_string = old_infer_string -if int(pd.__version__.split(",")[0]) >= 3: +if int(pd.__version__.split(".")[0]) >= 3: def _correct_pandas_string_none(dic: dict[str, str]): pass