We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Fix negative values in std
edit. There is an error in the numeric_utils.

This is a wrong order of operations

    std_devs = np.diag(cov ** 0.5)

Correct order is

     std_devs = np.diag(cov) ** 0.5

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `arviz/numeric_utils.py`
Content:
```
1 """Numerical utility functions for ArviZ."""
2 import warnings
3 import numpy as np
4 from scipy.signal import convolve, convolve2d
5 from scipy.signal.windows import gaussian
6 from scipy.sparse import coo_matrix
7 
8 from .stats.stats_utils import histogram
9 from .utils import _stack, _dot, _cov
10 
11 
12 def _fast_kde(x, cumulative=False, bw=4.5, xmin=None, xmax=None):
13     """Fast Fourier transform-based Gaussian kernel density estimate (KDE).
14 
15     The code was adapted from https://github.com/mfouesneau/faststats
16 
17     Parameters
18     ----------
19     x : Numpy array or list
20     cumulative : bool
21         If true, estimate the cdf instead of the pdf
22     bw : float
23         Bandwidth scaling factor for the KDE. Should be larger than 0. The higher this number the
24         smoother the KDE will be. Defaults to 4.5 which is essentially the same as the Scott's rule
25         of thumb (the default rule used by SciPy).
26     xmin : float
27         Manually set lower limit.
28     xmax : float
29         Manually set upper limit.
30 
31     Returns
32     -------
33     density: A gridded 1D KDE of the input points (x)
34     xmin: minimum value of x
35     xmax: maximum value of x
36     """
37     x = np.asarray(x, dtype=float)
38     x = x[np.isfinite(x)]
39     if x.size == 0:
40         warnings.warn("kde plot failed, you may want to check your data")
41         return np.array([np.nan]), np.nan, np.nan
42 
43     len_x = len(x)
44     n_points = 200 if (xmin or xmax) is None else 500
45 
46     if xmin is None:
47         xmin = np.min(x)
48     if xmax is None:
49         xmax = np.max(x)
50 
51     assert np.min(x) >= xmin
52     assert np.max(x) <= xmax
53 
54     log_len_x = np.log(len_x) * bw
55 
56     n_bins = min(int(len_x ** (1 / 3) * log_len_x * 2), n_points)
57     if n_bins < 2:
58         warnings.warn("kde plot failed, you may want to check your data")
59         return np.array([np.nan]), np.nan, np.nan
60 
61     # hist, bin_edges = np.histogram(x, bins=n_bins, range=(xmin, xmax))
62     # grid = hist / (hist.sum() * np.diff(bin_edges))
63 
64     _, grid, _ = histogram(x, n_bins, range_hist=(xmin, xmax))
65 
66     scotts_factor = len_x ** (-0.2)
67     kern_nx = int(scotts_factor * 2 * np.pi * log_len_x)
68     kernel = gaussian(kern_nx, scotts_factor * log_len_x)
69 
70     npad = min(n_bins, 2 * kern_nx)
71     grid = np.concatenate([grid[npad:0:-1], grid, grid[n_bins : n_bins - npad : -1]])
72     density = convolve(grid, kernel, mode="same", method="direct")[npad : npad + n_bins]
73     norm_factor = (2 * np.pi * log_len_x ** 2 * scotts_factor ** 2) ** 0.5
74 
75     density /= norm_factor
76 
77     if cumulative:
78         density = density.cumsum() / density.sum()
79 
80     return density, xmin, xmax
81 
82 
83 def _fast_kde_2d(x, y, gridsize=(128, 128), circular=False):
84     """
85     2D fft-based Gaussian kernel density estimate (KDE).
86 
87     The code was adapted from https://github.com/mfouesneau/faststats
88 
89     Parameters
90     ----------
91     x : Numpy array or list
92     y : Numpy array or list
93     gridsize : tuple
94         Number of points used to discretize data. Use powers of 2 for fft optimization
95     circular: bool
96         If True, use circular boundaries. Defaults to False
97     Returns
98     -------
99     grid: A gridded 2D KDE of the input points (x, y)
100     xmin: minimum value of x
101     xmax: maximum value of x
102     ymin: minimum value of y
103     ymax: maximum value of y
104     """
105     x = np.asarray(x, dtype=float)
106     x = x[np.isfinite(x)]
107     y = np.asarray(y, dtype=float)
108     y = y[np.isfinite(y)]
109 
110     xmin, xmax = x.min(), x.max()
111     ymin, ymax = y.min(), y.max()
112 
113     len_x = len(x)
114     weights = np.ones(len_x)
115     n_x, n_y = gridsize
116 
117     d_x = (xmax - xmin) / (n_x - 1)
118     d_y = (ymax - ymin) / (n_y - 1)
119 
120     xyi = _stack(x, y).T
121     xyi -= [xmin, ymin]
122     xyi /= [d_x, d_y]
123     xyi = np.floor(xyi, xyi).T
124 
125     scotts_factor = len_x ** (-1 / 6)
126     cov = _cov(xyi)
127     std_devs = np.diag(cov ** 0.5)
128     kern_nx, kern_ny = np.round(scotts_factor * 2 * np.pi * std_devs)
129 
130     inv_cov = np.linalg.inv(cov * scotts_factor ** 2)
131 
132     x_x = np.arange(kern_nx) - kern_nx / 2
133     y_y = np.arange(kern_ny) - kern_ny / 2
134     x_x, y_y = np.meshgrid(x_x, y_y)
135 
136     kernel = _stack(x_x.flatten(), y_y.flatten())
137     kernel = _dot(inv_cov, kernel) * kernel
138     kernel = np.exp(-kernel.sum(axis=0) / 2)
139     kernel = kernel.reshape((int(kern_ny), int(kern_nx)))
140 
141     boundary = "wrap" if circular else "symm"
142 
143     grid = coo_matrix((weights, xyi), shape=(n_x, n_y)).toarray()
144     grid = convolve2d(grid, kernel, mode="same", boundary=boundary)
145 
146     norm_factor = np.linalg.det(2 * np.pi * cov * scotts_factor ** 2)
147     norm_factor = len_x * d_x * d_y * norm_factor ** 0.5
148 
149     grid /= norm_factor
150 
151     return grid, xmin, xmax, ymin, ymax
152 
153 
154 def get_bins(values):
155     """
156     Automatically compute the number of bins for discrete variables.
157 
158     Parameters
159     ----------
160     values = numpy array
161         values
162 
163     Returns
164     -------
165     array with the bins
166 
167     Notes
168     -----
169     Computes the width of the bins by taking the maximun of the Sturges and the Freedman-Diaconis
170     estimators. Acording to numpy `np.histogram` this provides good all around performance.
171 
172     The Sturges is a very simplistic estimator based on the assumption of normality of the data.
173     This estimator has poor performance for non-normal data, which becomes especially obvious for
174     large data sets. The estimate depends only on size of the data.
175 
176     The Freedman-Diaconis rule uses interquartile range (IQR) to estimate the binwidth.
177     It is considered a robusts version of the Scott rule as the IQR is less affected by outliers
178     than the standard deviation. However, the IQR depends on fewer points than the standard
179     deviation, so it is less accurate, especially for long tailed distributions.
180     """
181     x_min = values.min().astype(int)
182     x_max = values.max().astype(int)
183 
184     # Sturges histogram bin estimator
185     bins_sturges = (x_max - x_min) / (np.log2(values.size) + 1)
186 
187     # The Freedman-Diaconis histogram bin estimator.
188     iqr = np.subtract(*np.percentile(values, [75, 25]))  # pylint: disable=assignment-from-no-return
189     bins_fd = 2 * iqr * values.size ** (-1 / 3)
190 
191     width = np.round(np.max([1, bins_sturges, bins_fd])).astype(int)
192 
193     return np.arange(x_min, x_max + width + 1, width)
194 
195 
196 def _sturges_formula(dataset, mult=1):
197     """Use Sturges' formula to determine number of bins.
198 
199     See https://en.wikipedia.org/wiki/Histogram#Sturges'_formula
200     or https://doi.org/10.1080%2F01621459.1926.10502161
201 
202     Parameters
203     ----------
204     dataset: xarray.DataSet
205         Must have the `draw` dimension
206 
207     mult: float
208         Used to scale the number of bins up or down. Default is 1 for Sturges' formula.
209 
210     Returns
211     -------
212     int
213         Number of bins to use
214     """
215     return int(np.ceil(mult * np.log2(dataset.draw.size)) + 1)
216
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/arviz/numeric_utils.py b/arviz/numeric_utils.py
--- a/arviz/numeric_utils.py
+++ b/arviz/numeric_utils.py
@@ -124,7 +124,7 @@
 
     scotts_factor = len_x ** (-1 / 6)
     cov = _cov(xyi)
-    std_devs = np.diag(cov ** 0.5)
+    std_devs = np.diag(cov) ** 0.5
     kern_nx, kern_ny = np.round(scotts_factor * 2 * np.pi * std_devs)
 
     inv_cov = np.linalg.inv(cov * scotts_factor ** 2)

{"golden_diff": "diff --git a/arviz/numeric_utils.py b/arviz/numeric_utils.py\n--- a/arviz/numeric_utils.py\n+++ b/arviz/numeric_utils.py\n@@ -124,7 +124,7 @@\n \n     scotts_factor = len_x ** (-1 / 6)\n     cov = _cov(xyi)\n-    std_devs = np.diag(cov ** 0.5)\n+    std_devs = np.diag(cov) ** 0.5\n     kern_nx, kern_ny = np.round(scotts_factor * 2 * np.pi * std_devs)\n \n     inv_cov = np.linalg.inv(cov * scotts_factor ** 2)\n", "issue": "Fix negative values in std\nedit. There is an error in the numeric_utils.\r\n\r\nThis is a wrong order of operations\r\n\r\n    std_devs = np.diag(cov ** 0.5)\r\n\r\nCorrect order is\r\n\r\n     std_devs = np.diag(cov) ** 0.5\n", "before_files": [{"content": "\"\"\"Numerical utility functions for ArviZ.\"\"\"\nimport warnings\nimport numpy as np\nfrom scipy.signal import convolve, convolve2d\nfrom scipy.signal.windows import gaussian\nfrom scipy.sparse import coo_matrix\n\nfrom .stats.stats_utils import histogram\nfrom .utils import _stack, _dot, _cov\n\n\ndef _fast_kde(x, cumulative=False, bw=4.5, xmin=None, xmax=None):\n    \"\"\"Fast Fourier transform-based Gaussian kernel density estimate (KDE).\n\n    The code was adapted from https://github.com/mfouesneau/faststats\n\n    Parameters\n    ----------\n    x : Numpy array or list\n    cumulative : bool\n        If true, estimate the cdf instead of the pdf\n    bw : float\n        Bandwidth scaling factor for the KDE. Should be larger than 0. The higher this number the\n        smoother the KDE will be. Defaults to 4.5 which is essentially the same as the Scott's rule\n        of thumb (the default rule used by SciPy).\n    xmin : float\n        Manually set lower limit.\n    xmax : float\n        Manually set upper limit.\n\n    Returns\n    -------\n    density: A gridded 1D KDE of the input points (x)\n    xmin: minimum value of x\n    xmax: maximum value of x\n    \"\"\"\n    x = np.asarray(x, dtype=float)\n    x = x[np.isfinite(x)]\n    if x.size == 0:\n        warnings.warn(\"kde plot failed, you may want to check your data\")\n        return np.array([np.nan]), np.nan, np.nan\n\n    len_x = len(x)\n    n_points = 200 if (xmin or xmax) is None else 500\n\n    if xmin is None:\n        xmin = np.min(x)\n    if xmax is None:\n        xmax = np.max(x)\n\n    assert np.min(x) >= xmin\n    assert np.max(x) <= xmax\n\n    log_len_x = np.log(len_x) * bw\n\n    n_bins = min(int(len_x ** (1 / 3) * log_len_x * 2), n_points)\n    if n_bins < 2:\n        warnings.warn(\"kde plot failed, you may want to check your data\")\n        return np.array([np.nan]), np.nan, np.nan\n\n    # hist, bin_edges = np.histogram(x, bins=n_bins, range=(xmin, xmax))\n    # grid = hist / (hist.sum() * np.diff(bin_edges))\n\n    _, grid, _ = histogram(x, n_bins, range_hist=(xmin, xmax))\n\n    scotts_factor = len_x ** (-0.2)\n    kern_nx = int(scotts_factor * 2 * np.pi * log_len_x)\n    kernel = gaussian(kern_nx, scotts_factor * log_len_x)\n\n    npad = min(n_bins, 2 * kern_nx)\n    grid = np.concatenate([grid[npad:0:-1], grid, grid[n_bins : n_bins - npad : -1]])\n    density = convolve(grid, kernel, mode=\"same\", method=\"direct\")[npad : npad + n_bins]\n    norm_factor = (2 * np.pi * log_len_x ** 2 * scotts_factor ** 2) ** 0.5\n\n    density /= norm_factor\n\n    if cumulative:\n        density = density.cumsum() / density.sum()\n\n    return density, xmin, xmax\n\n\ndef _fast_kde_2d(x, y, gridsize=(128, 128), circular=False):\n    \"\"\"\n    2D fft-based Gaussian kernel density estimate (KDE).\n\n    The code was adapted from https://github.com/mfouesneau/faststats\n\n    Parameters\n    ----------\n    x : Numpy array or list\n    y : Numpy array or list\n    gridsize : tuple\n        Number of points used to discretize data. Use powers of 2 for fft optimization\n    circular: bool\n        If True, use circular boundaries. Defaults to False\n    Returns\n    -------\n    grid: A gridded 2D KDE of the input points (x, y)\n    xmin: minimum value of x\n    xmax: maximum value of x\n    ymin: minimum value of y\n    ymax: maximum value of y\n    \"\"\"\n    x = np.asarray(x, dtype=float)\n    x = x[np.isfinite(x)]\n    y = np.asarray(y, dtype=float)\n    y = y[np.isfinite(y)]\n\n    xmin, xmax = x.min(), x.max()\n    ymin, ymax = y.min(), y.max()\n\n    len_x = len(x)\n    weights = np.ones(len_x)\n    n_x, n_y = gridsize\n\n    d_x = (xmax - xmin) / (n_x - 1)\n    d_y = (ymax - ymin) / (n_y - 1)\n\n    xyi = _stack(x, y).T\n    xyi -= [xmin, ymin]\n    xyi /= [d_x, d_y]\n    xyi = np.floor(xyi, xyi).T\n\n    scotts_factor = len_x ** (-1 / 6)\n    cov = _cov(xyi)\n    std_devs = np.diag(cov ** 0.5)\n    kern_nx, kern_ny = np.round(scotts_factor * 2 * np.pi * std_devs)\n\n    inv_cov = np.linalg.inv(cov * scotts_factor ** 2)\n\n    x_x = np.arange(kern_nx) - kern_nx / 2\n    y_y = np.arange(kern_ny) - kern_ny / 2\n    x_x, y_y = np.meshgrid(x_x, y_y)\n\n    kernel = _stack(x_x.flatten(), y_y.flatten())\n    kernel = _dot(inv_cov, kernel) * kernel\n    kernel = np.exp(-kernel.sum(axis=0) / 2)\n    kernel = kernel.reshape((int(kern_ny), int(kern_nx)))\n\n    boundary = \"wrap\" if circular else \"symm\"\n\n    grid = coo_matrix((weights, xyi), shape=(n_x, n_y)).toarray()\n    grid = convolve2d(grid, kernel, mode=\"same\", boundary=boundary)\n\n    norm_factor = np.linalg.det(2 * np.pi * cov * scotts_factor ** 2)\n    norm_factor = len_x * d_x * d_y * norm_factor ** 0.5\n\n    grid /= norm_factor\n\n    return grid, xmin, xmax, ymin, ymax\n\n\ndef get_bins(values):\n    \"\"\"\n    Automatically compute the number of bins for discrete variables.\n\n    Parameters\n    ----------\n    values = numpy array\n        values\n\n    Returns\n    -------\n    array with the bins\n\n    Notes\n    -----\n    Computes the width of the bins by taking the maximun of the Sturges and the Freedman-Diaconis\n    estimators. Acording to numpy `np.histogram` this provides good all around performance.\n\n    The Sturges is a very simplistic estimator based on the assumption of normality of the data.\n    This estimator has poor performance for non-normal data, which becomes especially obvious for\n    large data sets. The estimate depends only on size of the data.\n\n    The Freedman-Diaconis rule uses interquartile range (IQR) to estimate the binwidth.\n    It is considered a robusts version of the Scott rule as the IQR is less affected by outliers\n    than the standard deviation. However, the IQR depends on fewer points than the standard\n    deviation, so it is less accurate, especially for long tailed distributions.\n    \"\"\"\n    x_min = values.min().astype(int)\n    x_max = values.max().astype(int)\n\n    # Sturges histogram bin estimator\n    bins_sturges = (x_max - x_min) / (np.log2(values.size) + 1)\n\n    # The Freedman-Diaconis histogram bin estimator.\n    iqr = np.subtract(*np.percentile(values, [75, 25]))  # pylint: disable=assignment-from-no-return\n    bins_fd = 2 * iqr * values.size ** (-1 / 3)\n\n    width = np.round(np.max([1, bins_sturges, bins_fd])).astype(int)\n\n    return np.arange(x_min, x_max + width + 1, width)\n\n\ndef _sturges_formula(dataset, mult=1):\n    \"\"\"Use Sturges' formula to determine number of bins.\n\n    See https://en.wikipedia.org/wiki/Histogram#Sturges'_formula\n    or https://doi.org/10.1080%2F01621459.1926.10502161\n\n    Parameters\n    ----------\n    dataset: xarray.DataSet\n        Must have the `draw` dimension\n\n    mult: float\n        Used to scale the number of bins up or down. Default is 1 for Sturges' formula.\n\n    Returns\n    -------\n    int\n        Number of bins to use\n    \"\"\"\n    return int(np.ceil(mult * np.log2(dataset.draw.size)) + 1)\n", "path": "arviz/numeric_utils.py"}], "after_files": [{"content": "\"\"\"Numerical utility functions for ArviZ.\"\"\"\nimport warnings\nimport numpy as np\nfrom scipy.signal import convolve, convolve2d\nfrom scipy.signal.windows import gaussian\nfrom scipy.sparse import coo_matrix\n\nfrom .stats.stats_utils import histogram\nfrom .utils import _stack, _dot, _cov\n\n\ndef _fast_kde(x, cumulative=False, bw=4.5, xmin=None, xmax=None):\n    \"\"\"Fast Fourier transform-based Gaussian kernel density estimate (KDE).\n\n    The code was adapted from https://github.com/mfouesneau/faststats\n\n    Parameters\n    ----------\n    x : Numpy array or list\n    cumulative : bool\n        If true, estimate the cdf instead of the pdf\n    bw : float\n        Bandwidth scaling factor for the KDE. Should be larger than 0. The higher this number the\n        smoother the KDE will be. Defaults to 4.5 which is essentially the same as the Scott's rule\n        of thumb (the default rule used by SciPy).\n    xmin : float\n        Manually set lower limit.\n    xmax : float\n        Manually set upper limit.\n\n    Returns\n    -------\n    density: A gridded 1D KDE of the input points (x)\n    xmin: minimum value of x\n    xmax: maximum value of x\n    \"\"\"\n    x = np.asarray(x, dtype=float)\n    x = x[np.isfinite(x)]\n    if x.size == 0:\n        warnings.warn(\"kde plot failed, you may want to check your data\")\n        return np.array([np.nan]), np.nan, np.nan\n\n    len_x = len(x)\n    n_points = 200 if (xmin or xmax) is None else 500\n\n    if xmin is None:\n        xmin = np.min(x)\n    if xmax is None:\n        xmax = np.max(x)\n\n    assert np.min(x) >= xmin\n    assert np.max(x) <= xmax\n\n    log_len_x = np.log(len_x) * bw\n\n    n_bins = min(int(len_x ** (1 / 3) * log_len_x * 2), n_points)\n    if n_bins < 2:\n        warnings.warn(\"kde plot failed, you may want to check your data\")\n        return np.array([np.nan]), np.nan, np.nan\n\n    # hist, bin_edges = np.histogram(x, bins=n_bins, range=(xmin, xmax))\n    # grid = hist / (hist.sum() * np.diff(bin_edges))\n\n    _, grid, _ = histogram(x, n_bins, range_hist=(xmin, xmax))\n\n    scotts_factor = len_x ** (-0.2)\n    kern_nx = int(scotts_factor * 2 * np.pi * log_len_x)\n    kernel = gaussian(kern_nx, scotts_factor * log_len_x)\n\n    npad = min(n_bins, 2 * kern_nx)\n    grid = np.concatenate([grid[npad:0:-1], grid, grid[n_bins : n_bins - npad : -1]])\n    density = convolve(grid, kernel, mode=\"same\", method=\"direct\")[npad : npad + n_bins]\n    norm_factor = (2 * np.pi * log_len_x ** 2 * scotts_factor ** 2) ** 0.5\n\n    density /= norm_factor\n\n    if cumulative:\n        density = density.cumsum() / density.sum()\n\n    return density, xmin, xmax\n\n\ndef _fast_kde_2d(x, y, gridsize=(128, 128), circular=False):\n    \"\"\"\n    2D fft-based Gaussian kernel density estimate (KDE).\n\n    The code was adapted from https://github.com/mfouesneau/faststats\n\n    Parameters\n    ----------\n    x : Numpy array or list\n    y : Numpy array or list\n    gridsize : tuple\n        Number of points used to discretize data. Use powers of 2 for fft optimization\n    circular: bool\n        If True, use circular boundaries. Defaults to False\n    Returns\n    -------\n    grid: A gridded 2D KDE of the input points (x, y)\n    xmin: minimum value of x\n    xmax: maximum value of x\n    ymin: minimum value of y\n    ymax: maximum value of y\n    \"\"\"\n    x = np.asarray(x, dtype=float)\n    x = x[np.isfinite(x)]\n    y = np.asarray(y, dtype=float)\n    y = y[np.isfinite(y)]\n\n    xmin, xmax = x.min(), x.max()\n    ymin, ymax = y.min(), y.max()\n\n    len_x = len(x)\n    weights = np.ones(len_x)\n    n_x, n_y = gridsize\n\n    d_x = (xmax - xmin) / (n_x - 1)\n    d_y = (ymax - ymin) / (n_y - 1)\n\n    xyi = _stack(x, y).T\n    xyi -= [xmin, ymin]\n    xyi /= [d_x, d_y]\n    xyi = np.floor(xyi, xyi).T\n\n    scotts_factor = len_x ** (-1 / 6)\n    cov = _cov(xyi)\n    std_devs = np.diag(cov) ** 0.5\n    kern_nx, kern_ny = np.round(scotts_factor * 2 * np.pi * std_devs)\n\n    inv_cov = np.linalg.inv(cov * scotts_factor ** 2)\n\n    x_x = np.arange(kern_nx) - kern_nx / 2\n    y_y = np.arange(kern_ny) - kern_ny / 2\n    x_x, y_y = np.meshgrid(x_x, y_y)\n\n    kernel = _stack(x_x.flatten(), y_y.flatten())\n    kernel = _dot(inv_cov, kernel) * kernel\n    kernel = np.exp(-kernel.sum(axis=0) / 2)\n    kernel = kernel.reshape((int(kern_ny), int(kern_nx)))\n\n    boundary = \"wrap\" if circular else \"symm\"\n\n    grid = coo_matrix((weights, xyi), shape=(n_x, n_y)).toarray()\n    grid = convolve2d(grid, kernel, mode=\"same\", boundary=boundary)\n\n    norm_factor = np.linalg.det(2 * np.pi * cov * scotts_factor ** 2)\n    norm_factor = len_x * d_x * d_y * norm_factor ** 0.5\n\n    grid /= norm_factor\n\n    return grid, xmin, xmax, ymin, ymax\n\n\ndef get_bins(values):\n    \"\"\"\n    Automatically compute the number of bins for discrete variables.\n\n    Parameters\n    ----------\n    values = numpy array\n        values\n\n    Returns\n    -------\n    array with the bins\n\n    Notes\n    -----\n    Computes the width of the bins by taking the maximun of the Sturges and the Freedman-Diaconis\n    estimators. Acording to numpy `np.histogram` this provides good all around performance.\n\n    The Sturges is a very simplistic estimator based on the assumption of normality of the data.\n    This estimator has poor performance for non-normal data, which becomes especially obvious for\n    large data sets. The estimate depends only on size of the data.\n\n    The Freedman-Diaconis rule uses interquartile range (IQR) to estimate the binwidth.\n    It is considered a robusts version of the Scott rule as the IQR is less affected by outliers\n    than the standard deviation. However, the IQR depends on fewer points than the standard\n    deviation, so it is less accurate, especially for long tailed distributions.\n    \"\"\"\n    x_min = values.min().astype(int)\n    x_max = values.max().astype(int)\n\n    # Sturges histogram bin estimator\n    bins_sturges = (x_max - x_min) / (np.log2(values.size) + 1)\n\n    # The Freedman-Diaconis histogram bin estimator.\n    iqr = np.subtract(*np.percentile(values, [75, 25]))  # pylint: disable=assignment-from-no-return\n    bins_fd = 2 * iqr * values.size ** (-1 / 3)\n\n    width = np.round(np.max([1, bins_sturges, bins_fd])).astype(int)\n\n    return np.arange(x_min, x_max + width + 1, width)\n\n\ndef _sturges_formula(dataset, mult=1):\n    \"\"\"Use Sturges' formula to determine number of bins.\n\n    See https://en.wikipedia.org/wiki/Histogram#Sturges'_formula\n    or https://doi.org/10.1080%2F01621459.1926.10502161\n\n    Parameters\n    ----------\n    dataset: xarray.DataSet\n        Must have the `draw` dimension\n\n    mult: float\n        Used to scale the number of bins up or down. Default is 1 for Sturges' formula.\n\n    Returns\n    -------\n    int\n        Number of bins to use\n    \"\"\"\n    return int(np.ceil(mult * np.log2(dataset.draw.size)) + 1)\n", "path": "arviz/numeric_utils.py"}]}