Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dask:Data.seterr #384

Merged
merged 5 commits into from
Apr 22, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
200 changes: 0 additions & 200 deletions cf/data/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,30 +131,6 @@ def wrapper(*args, **kwargs):
_year_length = 365.242198781
_month_length = _year_length / 12

# --------------------------------------------------------------------
# _seterr = How floating-point errors in the results of arithmetic
# operations are handled. These defaults are those of
# numpy 1.10.1.
# --------------------------------------------------------------------
_seterr = {
"divide": "warn",
"invalid": "warn",
"over": "warn",
"under": "ignore",
}

# --------------------------------------------------------------------
# _seterr_raise_to_ignore = As _seterr but with any values of 'raise'
# changed to 'ignore'.
# --------------------------------------------------------------------
_seterr_raise_to_ignore = _seterr.copy()


for key, value in _seterr.items():
if value == "raise":
_seterr_raise_to_ignore[key] = "ignore"
# --- End: for

# --------------------------------------------------------------------
# _mask_fpe[0] = Whether or not to automatically set
# FloatingPointError exceptions to masked values in
Expand Down Expand Up @@ -5823,182 +5799,6 @@ def mask_fpe(*arg):

return old

@staticmethod
def seterr(all=None, divide=None, over=None, under=None, invalid=None):
"""Set how floating-point errors in the results of arithmetic
operations are handled.

The options for handling floating-point errors are:

============ ========================================================
Treatment Action
============ ========================================================
``'ignore'`` Take no action. Allows invalid values to occur in the
result data array.

``'warn'`` Print a `RuntimeWarning` (via the Python `warnings`
module). Allows invalid values to occur in the result
data array.

``'raise'`` Raise a `FloatingPointError` exception.
============ ========================================================

The different types of floating-point errors are:

================= ================================= =================
Error Description Default treatment
================= ================================= =================
Division by zero Infinite result obtained from ``'warn'``
finite numbers.

Overflow Result too large to be expressed. ``'warn'``

Invalid operation Result is not an expressible ``'warn'``
number, typically indicates that
a NaN was produced.

Underflow Result so close to zero that some ``'ignore'``
precision was lost.
================= ================================= =================

Note that operations on integer scalar types (such as int16) are
handled like floating point, and are affected by these settings.

If called without any arguments then the current behaviour is
returned.

.. seealso:: `cf.Data.mask_fpe`, `mask_invalid`

:Parameters:

all: `str`, optional
Set the treatment for all types of floating-point errors
at once. The default is not to change the current
behaviour.

divide: `str`, optional
Set the treatment for division by zero. The default is not
to change the current behaviour.

over: `str`, optional
Set the treatment for floating-point overflow. The default
is not to change the current behaviour.

under: `str`, optional
Set the treatment for floating-point underflow. The
default is not to change the current behaviour.

invalid: `str`, optional
Set the treatment for invalid floating-point
operation. The default is not to change the current
behaviour.

:Returns:

`dict`
The behaviour prior to the change, or the current
behaviour if no new values are specified.

**Examples**

Set treatment for all types of floating-point errors to
``'raise'`` and then reset to the previous behaviours:

>>> cf.Data.seterr()
{'divide': 'warn', 'invalid': 'warn', 'over': 'warn', 'under': 'ignore'}
>>> old = cf.Data.seterr('raise')
>>> cf.Data.seterr(**old)
{'divide': 'raise', 'invalid': 'raise', 'over': 'raise', 'under': 'raise'}
>>> cf.Data.seterr()
{'divide': 'warn', 'invalid': 'warn', 'over': 'warn', 'under': 'ignore'}

Set the treatment of division by zero to ``'ignore'`` and overflow
to ``'warn'`` without changing the treatment of underflow and
invalid operation:

>>> cf.Data.seterr(divide='ignore', over='warn')
{'divide': 'warn', 'invalid': 'warn', 'over': 'warn', 'under': 'ignore'}
>>> cf.Data.seterr()
{'divide': 'ignore', 'invalid': 'warn', 'over': 'ignore', 'under': 'ignore'}

Some examples with data arrays:

>>> d = cf.Data([0., 1])
>>> e = cf.Data([1., 2])

>>> old = cf.Data.seterr('ignore')
>>> e/d
<CF Data: [inf, 2.0] >
>>> e**12345
<CF Data: [1.0, inf] >

>>> cf.Data.seterr(divide='warn')
{'divide': 'ignore', 'invalid': 'ignore', 'over': 'ignore', 'under': 'ignore'}
>>> e/d
RuntimeWarning: divide by zero encountered in divide
<CF Data: [inf, 2.0] >
>>> e**12345
<CF Data: [1.0, inf] >

>>> old = cf.Data.mask_fpe(False)
>>> cf.Data.seterr(over='raise')
{'divide': 'warn', 'invalid': 'ignore', 'over': 'ignore', 'under': 'ignore'}
>>> e/d
RuntimeWarning: divide by zero encountered in divide
<CF Data: [inf, 2.0] >
>>> e**12345
FloatingPointError: overflow encountered in power

>>> cf.Data.mask_fpe(True)
False
>>> cf.Data.seterr(divide='ignore')
{'divide': 'warn', 'invalid': 'ignore', 'over': 'raise', 'under': 'ignore'}
>>> e/d
<CF Data: [inf, 2.0] >
>>> e**12345
<CF Data: [1.0, --] >

"""
old = _seterr.copy()

if all:
_seterr.update(
{"divide": all, "invalid": all, "under": all, "over": all}
)
if all == "raise":
_seterr_raise_to_ignore.update(
{
"divide": "ignore",
"invalid": "ignore",
"under": "ignore",
"over": "ignore",
}
)

else:
if divide:
_seterr["divide"] = divide
if divide == "raise":
_seterr_raise_to_ignore["divide"] = "ignore"

if over:
_seterr["over"] = over
if over == "raise":
_seterr_raise_to_ignore["over"] = "ignore"

if under:
_seterr["under"] = under
if under == "raise":
_seterr_raise_to_ignore["under"] = "ignore"

if invalid:
_seterr["invalid"] = invalid
if invalid == "raise":
_seterr_raise_to_ignore["invalid"] = "ignore"
# --- End: if

return old

# `arctan2`, AT2 seealso
@daskified(_DASKIFIED_VERBOSE)
@_inplace_enabled(default=False)
Expand Down
149 changes: 149 additions & 0 deletions cf/data/mixin/deprecations.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from ...functions import (
_DEPRECATION_ERROR_ATTRIBUTE,
_DEPRECATION_ERROR_METHOD,
DeprecationError,
)


Expand Down Expand Up @@ -386,3 +387,151 @@ def partition_boundaries(self):
_DEPRECATION_ERROR_METHOD(
"TODODASK - consider using 'chunks' instead"
) # pragma: no cover

@staticmethod
def seterr(all=None, divide=None, over=None, under=None, invalid=None):
"""Set how floating-point errors in the results of arithmetic
operations are handled.

Deprecated at version TODODASK. It is currently not possible
to control how floating-point errors are handled, due to the
use of `dask` for handling all array manipulations. This may
change in the future (see
https://github.com/dask/dask/issues/3245 for more details).

The options for handling floating-point errors are:

============ ========================================================
Treatment Action
============ ========================================================
``'ignore'`` Take no action. Allows invalid values to occur in the
result data array.

``'warn'`` Print a `RuntimeWarning` (via the Python `warnings`
module). Allows invalid values to occur in the result
data array.

``'raise'`` Raise a `FloatingPointError` exception.
============ ========================================================

The different types of floating-point errors are:

================= ================================= =================
Error Description Default treatment
================= ================================= =================
Division by zero Infinite result obtained from ``'warn'``
finite numbers.

Overflow Result too large to be expressed. ``'warn'``

Invalid operation Result is not an expressible ``'warn'``
number, typically indicates that
a NaN was produced.

Underflow Result so close to zero that some ``'ignore'``
precision was lost.
================= ================================= =================

Note that operations on integer scalar types (such as int16) are
handled like floating point, and are affected by these settings.

If called without any arguments then the current behaviour is
returned.

.. seealso:: `cf.Data.mask_fpe`, `mask_invalid`

:Parameters:

all: `str`, optional
Set the treatment for all types of floating-point errors
at once. The default is not to change the current
behaviour.

divide: `str`, optional
Set the treatment for division by zero. The default is not
to change the current behaviour.

over: `str`, optional
Set the treatment for floating-point overflow. The default
is not to change the current behaviour.

under: `str`, optional
Set the treatment for floating-point underflow. The
default is not to change the current behaviour.

invalid: `str`, optional
Set the treatment for invalid floating-point
operation. The default is not to change the current
behaviour.

:Returns:

`dict`
The behaviour prior to the change, or the current
behaviour if no new values are specified.

**Examples:**

Set treatment for all types of floating-point errors to
``'raise'`` and then reset to the previous behaviours:

>>> cf.Data.seterr()
{'divide': 'warn', 'invalid': 'warn', 'over': 'warn', 'under': 'ignore'}
>>> old = cf.Data.seterr('raise')
>>> cf.Data.seterr(**old)
{'divide': 'raise', 'invalid': 'raise', 'over': 'raise', 'under': 'raise'}
>>> cf.Data.seterr()
{'divide': 'warn', 'invalid': 'warn', 'over': 'warn', 'under': 'ignore'}

Set the treatment of division by zero to ``'ignore'`` and overflow
to ``'warn'`` without changing the treatment of underflow and
invalid operation:

>>> cf.Data.seterr(divide='ignore', over='warn')
{'divide': 'warn', 'invalid': 'warn', 'over': 'warn', 'under': 'ignore'}
>>> cf.Data.seterr()
{'divide': 'ignore', 'invalid': 'warn', 'over': 'ignore', 'under': 'ignore'}

Some examples with data arrays:

>>> d = cf.Data([0., 1])
>>> e = cf.Data([1., 2])

>>> old = cf.Data.seterr('ignore')
>>> e/d
<CF Data: [inf, 2.0] >
>>> e**12345
<CF Data: [1.0, inf] >

>>> cf.Data.seterr(divide='warn')
{'divide': 'ignore', 'invalid': 'ignore', 'over': 'ignore', 'under': 'ignore'}
>>> e/d
RuntimeWarning: divide by zero encountered in divide
<CF Data: [inf, 2.0] >
>>> e**12345
<CF Data: [1.0, inf] >

>>> old = cf.Data.mask_fpe(False)
>>> cf.Data.seterr(over='raise')
{'divide': 'warn', 'invalid': 'ignore', 'over': 'ignore', 'under': 'ignore'}
>>> e/d
RuntimeWarning: divide by zero encountered in divide
<CF Data: [inf, 2.0] >
>>> e**12345
FloatingPointError: overflow encountered in power

>>> cf.Data.mask_fpe(True)
False
>>> cf.Data.seterr(divide='ignore')
{'divide': 'warn', 'invalid': 'ignore', 'over': 'raise', 'under': 'ignore'}
>>> e/d
<CF Data: [inf, 2.0] >
>>> e**12345
<CF Data: [1.0, --] >

"""
raise DeprecationError(
"Data method 'seterr' has been deprecated at version TODODASK "
"and is not available.\n\n"
"It is currently not possible to control how floating-point errors are handled, due to the use of `dask` for handling all array manipulations. This may change in the future (see https://github.com/dask/dask/issues/3245 for more details)."
davidhassell marked this conversation as resolved.
Show resolved Hide resolved
)
Loading