Repository: matplotlib/matplotlib
Pull request: Remove old normalising code from plt.hist
This PR does a few things:

- Add a test for a normed histogram
- Rename the variable `n` to `tops` to make the code more readable
- Remove the old code to normalize histograms. This is now handled with numpy
- Remove the old notes section about how numpy used to be broken (fixes #8333)

Problem statement:
Rely on numpy to properly normalize histograms with unequal bin widths
The source of `hist` contains the following snippets:
```
        Notes
        -----
        Until numpy release 1.5, the underlying numpy histogram function was
        incorrect with `normed`=`True` if bin sizes were unequal.  MPL
        inherited that error.  It is now corrected within MPL when using
        earlier numpy versions.
```
```
        # hist_kwargs = dict(range=range, normed=bool(normed))
        # We will handle the normed kwarg within mpl until we
        # get to the point of requiring numpy >= 1.5.
```
and code for manual handling of the `normed` kwarg.

Given that we now require numpy >=1.7.1, we should just use the `density` kwarg to numpy.histogram to do this, and remove our own implementation.

Hints from issue discussion:
https://github.com/matplotlib/matplotlib/pull/7856 is starting to move this direction.
So it turns out we're not actually testing normed histograms at all..... PR incoming

Commit message: Remove un-used code

Patch to review:
diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py
index 15ba96030a89..2c2b246ba654 100644
--- a/lib/matplotlib/axes/_axes.py
+++ b/lib/matplotlib/axes/_axes.py
@@ -5988,13 +5988,6 @@ def hist(self, x, bins=None, range=None, density=None, weights=None,
         --------
         hist2d : 2D histograms
 
-        Notes
-        -----
-        Until numpy release 1.5, the underlying numpy histogram function was
-        incorrect with ``normed=True`` if bin sizes were unequal.  MPL
-        inherited that error. It is now corrected within MPL when using
-        earlier numpy versions.
-
         """
         # Avoid shadowing the builtin.
         bin_range = range
@@ -6087,8 +6080,10 @@ def hist(self, x, bins=None, range=None, density=None, weights=None,
         else:
             hist_kwargs = dict(range=bin_range)
 
-        n = []
+        # List to store all the top coordinates of the histograms
+        tops = []
         mlast = None
+        # Loop through datasets
         for i in xrange(nx):
             # this will automatically overwrite bins,
             # so that each histogram uses the same bins
@@ -6096,29 +6091,26 @@ def hist(self, x, bins=None, range=None, density=None, weights=None,
             m = m.astype(float)  # causes problems later if it's an int
             if mlast is None:
                 mlast = np.zeros(len(bins)-1, m.dtype)
-            if density and not stacked:
-                db = np.diff(bins)
-                m = (m.astype(float) / db) / m.sum()
             if stacked:
-                if mlast is None:
-                    mlast = np.zeros(len(bins)-1, m.dtype)
                 m += mlast
                 mlast[:] = m
-            n.append(m)
+            tops.append(m)
 
+        # If a stacked density plot, normalize so the area of all the stacked
+        # histograms together is 1
         if stacked and density:
             db = np.diff(bins)
-            for m in n:
-                m[:] = (m.astype(float) / db) / n[-1].sum()
+            for m in tops:
+                m[:] = (m.astype(float) / db) / tops[-1].sum()
         if cumulative:
             slc = slice(None)
             if cbook.is_numlike(cumulative) and cumulative < 0:
                 slc = slice(None, None, -1)
 
             if density:
-                n = [(m * np.diff(bins))[slc].cumsum()[slc] for m in n]
+                tops = [(m * np.diff(bins))[slc].cumsum()[slc] for m in tops]
             else:
-                n = [m[slc].cumsum()[slc] for m in n]
+                tops = [m[slc].cumsum()[slc] for m in tops]
 
         patches = []
 
@@ -6136,7 +6128,7 @@ def hist(self, x, bins=None, range=None, density=None, weights=None,
 
             if rwidth is not None:
                 dr = np.clip(rwidth, 0, 1)
-            elif (len(n) > 1 and
+            elif (len(tops) > 1 and
                   ((not stacked) or rcParams['_internal.classic_mode'])):
                 dr = 0.8
             else:
@@ -6162,7 +6154,7 @@ def hist(self, x, bins=None, range=None, density=None, weights=None,
                 _barfunc = self.bar
                 bottom_kwarg = 'bottom'
 
-            for m, c in zip(n, color):
+            for m, c in zip(tops, color):
                 if bottom is None:
                     bottom = np.zeros(len(m))
                 if stacked:
@@ -6206,7 +6198,7 @@ def hist(self, x, bins=None, range=None, density=None, weights=None,
                     # For data that is normed to form a probability density,
                     # set to minimum data value / logbase
                     # (gives 1 full tick-label unit for the lowest filled bin)
-                    ndata = np.array(n)
+                    ndata = np.array(tops)
                     minimum = (np.min(ndata[ndata > 0])) / logbase
                 else:
                     # For non-normed (density = False) data,
@@ -6229,7 +6221,7 @@ def hist(self, x, bins=None, range=None, density=None, weights=None,
             fill = (histtype == 'stepfilled')
 
             xvals, yvals = [], []
-            for m in n:
+            for m in tops:
                 if stacked:
                     # starting point for drawing polygon
                     y[0] = y[1]
@@ -6292,9 +6284,9 @@ def hist(self, x, bins=None, range=None, density=None, weights=None,
                     p.set_label('_nolegend_')
 
         if nx == 1:
-            return n[0], bins, cbook.silent_list('Patch', patches[0])
+            return tops[0], bins, cbook.silent_list('Patch', patches[0])
         else:
-            return n, bins, cbook.silent_list('Lists of Patches', patches)
+            return tops, bins, cbook.silent_list('Lists of Patches', patches)
 
     @_preprocess_data(replace_names=["x", "y", "weights"], label_namer=None)
     def hist2d(self, x, y, bins=10, range=None, normed=False, weights=None,


Code review comments:
diff_hunk: @@ -1464,6 +1464,14 @@ def test_hist_step_filled():
     assert all([p.get_facecolor() == p.get_edgecolor() for p in patches])
 
 
+@image_comparison(baseline_images=['hist_density'], extensions=['png'])
+def test_hist_density():
+    np.random.seed(0)
path: lib/matplotlib/tests/test_axes.py
text: @user1:
Can you use 19680801 (JDH's birthday) as the seed?