diff --git a/qt/python/mantidqt/widgets/colorbar/__init__.py b/qt/python/mantidqt/widgets/colorbar/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..1d6beeb60af03d5f011fc43d4e12d4bdfddaea04
--- /dev/null
+++ b/qt/python/mantidqt/widgets/colorbar/__init__.py
@@ -0,0 +1,21 @@
+# Mantid Repository : https://github.com/mantidproject/mantid
+#
+# Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
+#     NScD Oak Ridge National Laboratory, European Spallation Source
+#     & Institut Laue - Langevin
+# SPDX - License - Identifier: GPL - 3.0 +
+#  This file is part of the mantid workbench.
+#
+#
+# Can be launch from python by _e.g_
+#
+#
+# from mantidqt.widgets.colorbar.colorbar import ColorbarWidget
+# from qtpy.QtWidgets import QApplication
+# import matplotlib.pyplot as plt
+# ax=plt.imshow([[0,1],[2,100]])
+# app = QApplication([])
+# window = ColorbarWidget()
+# window.set_mappable(ax)
+# window.show()
+# app.exec_()
diff --git a/qt/python/mantidqt/widgets/colorbar/colorbar.py b/qt/python/mantidqt/widgets/colorbar/colorbar.py
new file mode 100644
index 0000000000000000000000000000000000000000..c54b5893cea00106cb4881a274b60fa5434e9720
--- /dev/null
+++ b/qt/python/mantidqt/widgets/colorbar/colorbar.py
@@ -0,0 +1,181 @@
+# Mantid Repository : https://github.com/mantidproject/mantid
+#
+# Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
+#     NScD Oak Ridge National Laboratory, European Spallation Source
+#     & Institut Laue - Langevin
+# SPDX - License - Identifier: GPL - 3.0 +
+#  This file is part of the mantid workbench.
+#
+#
+from __future__ import (absolute_import, division, print_function)
+from qtpy.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QLineEdit, QComboBox, QCheckBox, QLabel
+from qtpy.QtCore import Signal
+from qtpy.QtGui import QDoubleValidator
+from matplotlib.colorbar import Colorbar
+from matplotlib.figure import Figure
+from mantidqt.MPLwidgets import FigureCanvas
+from matplotlib.colors import Normalize, SymLogNorm, PowerNorm
+
+
+NORM_OPTS = ["Linear", "SymmetricLog10", "Power"]
+
+
+class ColorbarWidget(QWidget):
+    colorbarChanged = Signal() # The parent should simply redraw their canvas
+
+    def __init__(self, parent=None):
+        super(ColorbarWidget, self).__init__(parent)
+
+        self.setWindowTitle("Colorbar")
+        self.setMaximumWidth(200)
+
+        self.dval = QDoubleValidator()
+
+        self.cmin = QLineEdit()
+        self.cmin_value = 0
+        self.cmin.setMaximumWidth(100)
+        self.cmin.editingFinished.connect(self.clim_changed)
+        self.cmin_layout = QHBoxLayout()
+        self.cmin_layout.addStretch()
+        self.cmin_layout.addWidget(self.cmin)
+        self.cmin_layout.addStretch()
+
+        self.cmax = QLineEdit()
+        self.cmax_value = 1
+        self.cmax.setMaximumWidth(100)
+        self.cmax.editingFinished.connect(self.clim_changed)
+        self.cmin.setValidator(self.dval)
+        self.cmax.setValidator(self.dval)
+        self.cmax_layout = QHBoxLayout()
+        self.cmax_layout.addStretch()
+        self.cmax_layout.addWidget(self.cmax)
+        self.cmax_layout.addStretch()
+
+        self.norm_layout = QHBoxLayout()
+        self.norm = QComboBox()
+        self.norm.addItems(NORM_OPTS)
+        self.norm.currentIndexChanged.connect(self.norm_changed)
+
+        self.powerscale = QLineEdit()
+        self.powerscale_value = 2
+        self.powerscale.setText("2")
+        self.powerscale.setValidator(QDoubleValidator(0.001,100,3))
+        self.powerscale.setMaximumWidth(50)
+        self.powerscale.editingFinished.connect(self.norm_changed)
+        self.powerscale.hide()
+        self.powerscale_label = QLabel("n=")
+        self.powerscale_label.hide()
+
+        self.norm_layout.addStretch()
+        self.norm_layout.addWidget(self.norm)
+        self.norm_layout.addStretch()
+        self.norm_layout.addWidget(self.powerscale_label)
+        self.norm_layout.addWidget(self.powerscale)
+
+        self.autoscale = QCheckBox("Autoscaling")
+        self.autoscale.setChecked(True)
+        self.autoscale.stateChanged.connect(self.update_clim)
+
+        self.canvas = FigureCanvas(Figure())
+        if parent:
+            # Set facecolor to match parent
+            self.canvas.figure.set_facecolor(parent.palette().window().color().getRgbF())
+        self.ax = self.canvas.figure.add_axes([0.4,0.05,0.2,0.9])
+
+        # layout
+        self.layout = QVBoxLayout(self)
+        self.layout.addLayout(self.cmax_layout)
+        self.layout.addWidget(self.canvas, stretch=1)
+        self.layout.addLayout(self.cmin_layout)
+        self.layout.addLayout(self.norm_layout)
+        self.layout.addWidget(self.autoscale)
+
+    def set_mappable(self, mappable):
+        """
+        When a new plot is created this method should be called with the new mappable
+        """
+        self.ax.clear()
+        self.colorbar = Colorbar(ax=self.ax, mappable=mappable)
+        self.cmin_value, self.cmax_value = self.colorbar.get_clim()
+        self.update_clim_text()
+        self.redraw()
+
+    def norm_changed(self):
+        """
+        Called when a different normalization is selected
+        """
+        idx = self.norm.currentIndex()
+        if NORM_OPTS[idx] == 'Power':
+            self.powerscale.show()
+            self.powerscale_label.show()
+        else:
+            self.powerscale.hide()
+            self.powerscale_label.hide()
+        self.colorbar.mappable.set_norm(self.get_norm())
+        self.colorbarChanged.emit()
+
+    def get_norm(self):
+        """
+        This will create a matplotlib.colors.Normalize from selected idx, limits and powerscale
+        """
+        idx = self.norm.currentIndex()
+        if self.autoscale.isChecked():
+            cmin = cmax = None
+        else:
+            cmin = self.cmin_value
+            cmax = self.cmax_value
+        if NORM_OPTS[idx] == 'Power':
+            if self.powerscale.hasAcceptableInput():
+                self.powerscale_value = float(self.powerscale.text())
+            return PowerNorm(gamma=self.powerscale_value, vmin=cmin, vmax=cmax)
+        elif NORM_OPTS[idx] == "SymmetricLog10":
+            return SymLogNorm(1e-8 if cmin is None else max(1e-8, abs(cmin)*1e-3),
+                              vmin=cmin, vmax=cmax)
+        else:
+            return Normalize(vmin=cmin, vmax=cmax)
+
+    def clim_changed(self):
+        """
+        Called when either the min or max is changed. Will unset the autoscale.
+        """
+        self.autoscale.blockSignals(True)
+        self.autoscale.setChecked(False)
+        self.autoscale.blockSignals(False)
+        self.update_clim()
+
+    def update_clim(self):
+        """
+        This will update the clim of the plot based on min, max, and autoscale
+        """
+        if self.autoscale.isChecked():
+            data = self.colorbar.mappable.get_array()
+            try:
+                self.cmin_value = data[~data.mask].min()
+                self.cmax_value = data[~data.mask].max()
+            except ValueError:
+                # all values mask
+                pass
+            self.update_clim_text()
+        else:
+            if self.cmin.hasAcceptableInput():
+                self.cmin_value = float(self.cmin.text())
+            if self.cmax.hasAcceptableInput():
+                self.cmax_value = float(self.cmax.text())
+        self.colorbar.set_clim(self.cmin_value, self.cmax_value)
+        self.redraw()
+
+    def update_clim_text(self):
+        """
+        Update displayed limit values based on stored ones
+        """
+        self.cmin.setText("{:.4}".format(self.cmin_value))
+        self.cmax.setText("{:.4}".format(self.cmax_value))
+
+    def redraw(self):
+        """
+        Redraws the colobar and emits signal to cause the parent to redraw
+        """
+        self.colorbar.update_ticks()
+        self.colorbar.draw_all()
+        self.canvas.draw_idle()
+        self.colorbarChanged.emit()
diff --git a/qt/python/mantidqt/widgets/sliceviewer/view.py b/qt/python/mantidqt/widgets/sliceviewer/view.py
index 8adc2106509853e52a0d2c822031a2b5713dc6e3..de7297573d0c4d86d08abb7b10dfafe778c180c8 100644
--- a/qt/python/mantidqt/widgets/sliceviewer/view.py
+++ b/qt/python/mantidqt/widgets/sliceviewer/view.py
@@ -8,11 +8,12 @@
 #
 #
 from __future__ import (absolute_import, division, print_function)
-from qtpy.QtWidgets import QWidget, QVBoxLayout
+from qtpy.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout
 from qtpy.QtCore import Qt
 from mantidqt.MPLwidgets import FigureCanvas, NavigationToolbar2QT as NavigationToolbar
 from matplotlib.figure import Figure
 from .dimensionwidget import DimensionWidget
+from mantidqt.widgets.colorbar.colorbar import ColorbarWidget
 
 
 class SliceViewerView(QWidget):
@@ -30,11 +31,17 @@ class SliceViewerView(QWidget):
         self.dimensions.dimensionsChanged.connect(self.presenter.new_plot)
         self.dimensions.valueChanged.connect(self.presenter.update_plot_data)
 
-        # MPL figure
+        # MPL figure + colorbar
+        self.mpl_layout = QHBoxLayout()
         self.fig = Figure()
+        self.fig.set_facecolor(self.palette().window().color().getRgbF())
         self.fig.set_tight_layout(True)
         self.canvas = FigureCanvas(self.fig)
         self.ax = self.fig.add_subplot(111, projection='mantid')
+        self.mpl_layout.addWidget(self.canvas)
+        self.colorbar = ColorbarWidget(self)
+        self.colorbar.colorbarChanged.connect(self.canvas.draw_idle)
+        self.mpl_layout.addWidget(self.colorbar)
 
         # MPL toolbar
         self.mpl_toolbar = NavigationToolbar(self.canvas, self)
@@ -43,7 +50,7 @@ class SliceViewerView(QWidget):
         self.layout = QVBoxLayout(self)
         self.layout.addWidget(self.dimensions)
         self.layout.addWidget(self.mpl_toolbar)
-        self.layout.addWidget(self.canvas, stretch=1)
+        self.layout.addLayout(self.mpl_layout, stretch=1)
 
         self.show()
 
@@ -52,23 +59,19 @@ class SliceViewerView(QWidget):
         clears the plot and creates a new one using the workspace
         """
         self.ax.clear()
-        try:
-            self.colorbar.remove()
-        except AttributeError:
-            pass
-        self.im = self.ax.imshow(ws, origin='lower', **kwargs)
+        self.im = self.ax.imshow(ws, origin='lower', aspect='auto',
+                                 norm=self.colorbar.get_norm(), **kwargs)
         self.ax.set_title('')
-        self.colorbar = self.fig.colorbar(self.im)
+        self.colorbar.set_mappable(self.im)
         self.mpl_toolbar.update() # clear nav stack
-        self.fig.canvas.draw_idle()
+        self.canvas.draw_idle()
 
     def update_plot_data(self, data):
         """
         This just updates the plot data without creating a new plot
         """
         self.im.set_data(data.T)
-        self.im.set_clim(data.min(), data.max())
-        self.fig.canvas.draw_idle()
+        self.colorbar.update_clim()
 
     def closeEvent(self, event):
         self.deleteLater()