Repository: holoviz/holoviews

Issue:
Strange rasterize colormapping in Large Data user guide
While discussing #4567 with @jbednar, we noticed the following strange output in the [Large Data User Guide](http://holoviews.org/user_guide/Large_Data.html)

![image](https://user-images.githubusercontent.com/890576/94418666-4f51d180-0147-11eb-8918-85b79149e7d9.png)

This looks pretty strange as it looks like the *reverse* of the [fire colormap](https://colorcet.holoviz.org/) where black is low and white is high as the raster holds positive counts with *higher* counts in the middle:

<img src="https://user-images.githubusercontent.com/890576/94418996-bc656700-0147-11eb-974e-4d51e63f56a5.png" width=300></img>

Initially I thought this might be related to the recent work in #4567 but then realized that it can't be as that PR hasn't been merged yet.

Presumably it used to look like the GIF shown for the next code cell (i.e normal fire with a black background)?

<img src="https://user-images.githubusercontent.com/890576/94419247-19611d00-0148-11eb-9766-58b0c360b6e2.png" width=500></img>



Discussion:
@philippjfr did say this was rather strange. As it is important to address, I'll assign it to the next milestone.
I've tracked this down and it looks like the fire colormap is currently inverted from what it should be:

![image](https://user-images.githubusercontent.com/890576/99796635-73041900-2af3-11eb-804d-c2b2b5db10d0.png)

whereas 'fire_r' looks like 'fire':

![image](https://user-images.githubusercontent.com/890576/99796589-5ff14900-2af3-11eb-9005-415938efdc7e.png)

This can't always have been wrong as the GIF above that is part of the notebook shows fire correctly. I have no idea how this happened but we should try to track it down as it is concerning.
Adding `hv.opts.defaults(hv.opts.Image(cmap='fire_r'))` to the top of the Large Data user guide 'fixes' this issue but doesn't explain why fire is reversed from what it should be.

Resolving patch:
diff --git a/holoviews/plotting/util.py b/holoviews/plotting/util.py
--- a/holoviews/plotting/util.py
+++ b/holoviews/plotting/util.py
@@ -595,7 +595,8 @@ def bokeh_palette_to_palette(cmap, ncolors=None, categorical=False):
         reverse = True
 
     # Some colormaps are inverted compared to matplotlib
-    inverted = (not cmap_categorical and not cmap.capitalize() in palettes.mpl)
+    inverted = (not cmap_categorical and not cmap.capitalize() in palettes.mpl
+                and not cmap.startswith('fire'))
     if inverted:
         reverse=not reverse
     ncolors = ncolors or 256
@@ -684,7 +685,10 @@ def info(provider,names):
     if 'matplotlib' in provider:
         try:
             import matplotlib.cm as cm
-            mpl_cmaps = list(cm.cmaps_listed)+list(cm.datad)
+            if hasattr(cm, '_cmap_registry'):
+                mpl_cmaps = list(cm._cmap_registry)
+            else:
+                mpl_cmaps = list(cm.cmaps_listed)+list(cm.datad)
             cmaps += info('matplotlib', mpl_cmaps)
             cmaps += info('matplotlib', [cmap+'_r' for cmap in mpl_cmaps])
         except:


Test patch:
diff --git a/holoviews/tests/plotting/testplotutils.py b/holoviews/tests/plotting/testplotutils.py
--- a/holoviews/tests/plotting/testplotutils.py
+++ b/holoviews/tests/plotting/testplotutils.py
@@ -1,6 +1,8 @@
 from __future__ import absolute_import, unicode_literals
 
-from unittest import SkipTest
+import sys
+
+from unittest import SkipTest, skipIf
 
 import numpy as np
 
@@ -24,6 +26,9 @@
 except:
     bokeh_renderer = None
 
+py2_skip = skipIf(sys.version_info.major == 2, "Not supported in python2")
+
+
 
 class TestOverlayableZorders(ComparisonTestCase):
 
@@ -468,17 +473,26 @@ class TestMPLColormapUtils(ComparisonTestCase):
     def setUp(self):
         try:
             import matplotlib.cm # noqa
+            import holoviews.plotting.mpl # noqa
         except:
             raise SkipTest("Matplotlib needed to test matplotlib colormap instances")
 
+    def test_mpl_colormap_fire(self):
+        colors = process_cmap('fire', 3, provider='matplotlib')
+        self.assertEqual(colors, ['#000000', '#ed1400', '#ffffff'])
+
+    def test_mpl_colormap_fire_r(self):
+        colors = process_cmap('fire_r', 3, provider='matplotlib')
+        self.assertEqual(colors, ['#ffffff', '#eb1300', '#000000'])
+
     def test_mpl_colormap_name_palette(self):
-        colors = process_cmap('Greys', 3)
+        colors = process_cmap('Greys', 3, provider='matplotlib')
         self.assertEqual(colors, ['#ffffff', '#959595', '#000000'])
 
     def test_mpl_colormap_instance(self):
         from matplotlib.cm import get_cmap
         cmap = get_cmap('Greys')
-        colors = process_cmap(cmap, 3)
+        colors = process_cmap(cmap, 3, provider='matplotlib')
         self.assertEqual(colors, ['#ffffff', '#959595', '#000000'])
 
     def test_mpl_colormap_categorical(self):
@@ -519,6 +533,7 @@ class TestBokehPaletteUtils(ComparisonTestCase):
     def setUp(self):
         try:
             import bokeh.palettes # noqa
+            import holoviews.plotting.bokeh # noqa
         except:
             raise SkipTest('Bokeh required to test bokeh palette utilities')
 
@@ -529,6 +544,16 @@ def test_bokeh_palette_categorical_palettes_not_interpolated(self):
         for cat in categorical:
             self.assertTrue(len(set(bokeh_palette_to_palette(cat))) <= 20)
 
+    @py2_skip
+    def test_bokeh_colormap_fire(self):
+        colors = process_cmap('fire', 3, provider='bokeh')
+        self.assertEqual(colors, ['#000000', '#eb1300', '#ffffff'])
+
+    @py2_skip
+    def test_bokeh_colormap_fire_r(self):
+        colors = process_cmap('fire_r', 3, provider='bokeh')
+        self.assertEqual(colors, ['#ffffff', '#ed1400', '#000000'])
+
     def test_bokeh_palette_categorical(self):
         colors = bokeh_palette_to_palette('Category20', 3)
         self.assertEqual(colors, ['#1f77b4', '#c5b0d5', '#9edae5'])