prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Updating of image ColorMapper
  The ability to change the low/high of a ColorMapper for an already existing image (adjusting contrast/brightness) through widget callbacks on a server is desired. I could imagine this being accomplished by the following code, which incidentally doesn't throw any errors as is, it just doesn't do anything ;)
  
  ```
  import numpy as np
  from bokeh.plotting import figure, curdoc
  from bokeh.layouts import row, layout
  from bokeh.models import Slider
  from bokeh.models.mappers import LinearColorMapper
  from bokeh.palettes import Greys9
  
  def change_image_contrast(attr, old, new):
      fig_im.glyph.color_mapper.update(low=graph_min_slider.value, high=graph_max_slider.value)
      fig_im.trigger('glyph', fig_im.glyph, fig_im.glyph)
  
  graph_min_slider = Slider(title="Min", start=0, end=99, step=1, value=0)
  graph_max_slider = Slider(title="Max", start=1, end=100, step=1, value=100)
  
  graph_min_slider.on_change('value', change_image_contrast)
  graph_max_slider.on_change('value', change_image_contrast)
  
  fig = figure(plot_width=500, plot_height=500, x_range=(0, 10), y_range=(0, 10))
  
  fig_im = fig.image(image=[np.random.randint(0, 100, (10, 10), dtype='int16')], x=[0], y=[0], dw=[10], dh=[10],
                     color_mapper=LinearColorMapper(low=0, high=100, palette=Greys9))
  
  curdoc().add_root(layout([fig], [row([graph_min_slider, graph_max_slider])]))
  ```
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `bokeh/models/mappers.py`
  Content:
  ```
  1 """ Models for mapping values from one range or space to another.
  2 
  3 """
  4 from __future__ import absolute_import
  5 
  6 from ..model import Model
  7 from ..core.properties import abstract
  8 from ..core.properties import Float, Color, Enum, Seq
  9 from ..core.enums import Palette
  10 from .. import palettes
  11 
  12 @abstract
  13 class ColorMapper(Model):
  14     """ Base class for color mapper types. `ColorMapper`` is not
  15     generally useful to instantiate on its own.
  16 
  17     """
  18 
  19 class LinearColorMapper(ColorMapper):
  20     """ Map numbers in a range [*low*, *high*] linearly into a
  21     sequence of colors (a palette).
  22 
  23     For example, if the range is [0, 99] and the palette is
  24     ``['red', 'green', 'blue']``, the values would be mapped as
  25     follows::
  26 
  27              x < 0  : 'red'     # values < low are clamped
  28         0 >= x < 33 : 'red'
  29        33 >= x < 66 : 'green'
  30        66 >= x < 99 : 'blue'
  31        99 >= x      : 'blue'    # values > high are clamped
  32 
  33     """
  34 
  35     palette = Seq(Color, help="""
  36     A sequence of colors to use as the target palette for mapping.
  37 
  38     This property can also be set as a ``String``, to the name of
  39     any of the palettes shown in :ref:`bokeh.palettes`.
  40     """).accepts(Enum(Palette), lambda pal: getattr(palettes, pal))
  41 
  42     low = Float(help="""
  43     The minimum value of the range to map into the palette. Values below
  44     this are clamped to ``low``.
  45     """)
  46 
  47     high = Float(help="""
  48     The maximum value of the range to map into the palette. Values above
  49     this are clamped to ``high``.
  50     """)
  51 
  52     # TODO: (jc) what is the color code for transparent?
  53     # TODO: (bev) better docstring
  54     reserve_color = Color("#ffffff", help="""
  55     Used by Abstract Rendering.
  56     """)
  57 
  58     # TODO: (bev) better docstring
  59     reserve_val = Float(default=None, help="""
  60     Used by Abstract Rendering.
  61     """)
  62 
  63     def __init__(self, palette=None, **kwargs):
  64         if palette is not None: kwargs['palette'] = palette
  65         super(LinearColorMapper, self).__init__(**kwargs)
  66 
  67 class LogColorMapper(ColorMapper):
  68     """ Map numbers in a range [*low*, *high*] into a
  69     sequence of colors (a palette) on a natural logarithm scale.
  70 
  71     For example, if the range is [0, 25] and the palette is
  72     ``['red', 'green', 'blue']``, the values would be mapped as
  73     follows::
  74 
  75                 x < 0     : 'red'     # values < low are clamped
  76        0     >= x < 2.72  : 'red'     # math.e ** 1
  77        2.72  >= x < 7.39  : 'green'   # math.e ** 2
  78        7.39  >= x < 20.09 : 'blue'    # math.e ** 3
  79        20.09 >= x         : 'blue'    # values > high are clamped
  80 
  81     .. warning::
  82         The LogColorMapper only works for images with scalar values that are
  83         non-negative.
  84 
  85     """
  86 
  87     palette = Seq(Color, help="""
  88     A sequence of colors to use as the target palette for mapping.
  89 
  90     This property can also be set as a ``String``, to the name of
  91     any of the palettes shown in :ref:`bokeh.palettes`.
  92     """).accepts(Enum(Palette), lambda pal: getattr(palettes, pal))
  93 
  94     low = Float(help="""
  95     The minimum value of the range to map into the palette. Values below
  96     this are clamped to ``low``.
  97     """)
  98 
  99     high = Float(help="""
  100     The maximum value of the range to map into the palette. Values above
  101     this are clamped to ``high``.
  102     """)
  103 
  104     def __init__(self, palette=None, **kwargs):
  105         if palette is not None: kwargs['palette'] = palette
  106         super(LogColorMapper, self).__init__(**kwargs)
  107
  ```
  --- 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()
  
  ```
  
golden_diff: diff --git a/bokeh/models/mappers.py b/bokeh/models/mappers.py
  --- a/bokeh/models/mappers.py
  +++ b/bokeh/models/mappers.py
  @@ -16,6 +16,17 @@
   
       """
   
  +    palette = Seq(Color, help="""
  +    A sequence of colors to use as the target palette for mapping.
  +
  +    This property can also be set as a ``String``, to the name of
  +    any of the palettes shown in :ref:`bokeh.palettes`.
  +    """).accepts(Enum(Palette), lambda pal: getattr(palettes, pal))
  +
  +    def __init__(self, palette=None, **kwargs):
  +        if palette is not None: kwargs['palette'] = palette
  +        super(ColorMapper, self).__init__(**kwargs)
  +
   class LinearColorMapper(ColorMapper):
       """ Map numbers in a range [*low*, *high*] linearly into a
       sequence of colors (a palette).
  @@ -32,13 +43,6 @@
   
       """
   
  -    palette = Seq(Color, help="""
  -    A sequence of colors to use as the target palette for mapping.
  -
  -    This property can also be set as a ``String``, to the name of
  -    any of the palettes shown in :ref:`bokeh.palettes`.
  -    """).accepts(Enum(Palette), lambda pal: getattr(palettes, pal))
  -
       low = Float(help="""
       The minimum value of the range to map into the palette. Values below
       this are clamped to ``low``.
  @@ -60,10 +64,6 @@
       Used by Abstract Rendering.
       """)
   
  -    def __init__(self, palette=None, **kwargs):
  -        if palette is not None: kwargs['palette'] = palette
  -        super(LinearColorMapper, self).__init__(**kwargs)
  -
   class LogColorMapper(ColorMapper):
       """ Map numbers in a range [*low*, *high*] into a
       sequence of colors (a palette) on a natural logarithm scale.
  @@ -84,13 +84,6 @@
   
       """
   
  -    palette = Seq(Color, help="""
  -    A sequence of colors to use as the target palette for mapping.
  -
  -    This property can also be set as a ``String``, to the name of
  -    any of the palettes shown in :ref:`bokeh.palettes`.
  -    """).accepts(Enum(Palette), lambda pal: getattr(palettes, pal))
  -
       low = Float(help="""
       The minimum value of the range to map into the palette. Values below
       this are clamped to ``low``.
  @@ -100,7 +93,3 @@
       The maximum value of the range to map into the palette. Values above
       this are clamped to ``high``.
       """)
  -
  -    def __init__(self, palette=None, **kwargs):
  -        if palette is not None: kwargs['palette'] = palette
  -        super(LogColorMapper, self).__init__(**kwargs)
  
verification_info: {"golden_diff": "diff --git a/bokeh/models/mappers.py b/bokeh/models/mappers.py\n--- a/bokeh/models/mappers.py\n+++ b/bokeh/models/mappers.py\n@@ -16,6 +16,17 @@\n \n     \"\"\"\n \n+    palette = Seq(Color, help=\"\"\"\n+    A sequence of colors to use as the target palette for mapping.\n+\n+    This property can also be set as a ``String``, to the name of\n+    any of the palettes shown in :ref:`bokeh.palettes`.\n+    \"\"\").accepts(Enum(Palette), lambda pal: getattr(palettes, pal))\n+\n+    def __init__(self, palette=None, **kwargs):\n+        if palette is not None: kwargs['palette'] = palette\n+        super(ColorMapper, self).__init__(**kwargs)\n+\n class LinearColorMapper(ColorMapper):\n     \"\"\" Map numbers in a range [*low*, *high*] linearly into a\n     sequence of colors (a palette).\n@@ -32,13 +43,6 @@\n \n     \"\"\"\n \n-    palette = Seq(Color, help=\"\"\"\n-    A sequence of colors to use as the target palette for mapping.\n-\n-    This property can also be set as a ``String``, to the name of\n-    any of the palettes shown in :ref:`bokeh.palettes`.\n-    \"\"\").accepts(Enum(Palette), lambda pal: getattr(palettes, pal))\n-\n     low = Float(help=\"\"\"\n     The minimum value of the range to map into the palette. Values below\n     this are clamped to ``low``.\n@@ -60,10 +64,6 @@\n     Used by Abstract Rendering.\n     \"\"\")\n \n-    def __init__(self, palette=None, **kwargs):\n-        if palette is not None: kwargs['palette'] = palette\n-        super(LinearColorMapper, self).__init__(**kwargs)\n-\n class LogColorMapper(ColorMapper):\n     \"\"\" Map numbers in a range [*low*, *high*] into a\n     sequence of colors (a palette) on a natural logarithm scale.\n@@ -84,13 +84,6 @@\n \n     \"\"\"\n \n-    palette = Seq(Color, help=\"\"\"\n-    A sequence of colors to use as the target palette for mapping.\n-\n-    This property can also be set as a ``String``, to the name of\n-    any of the palettes shown in :ref:`bokeh.palettes`.\n-    \"\"\").accepts(Enum(Palette), lambda pal: getattr(palettes, pal))\n-\n     low = Float(help=\"\"\"\n     The minimum value of the range to map into the palette. Values below\n     this are clamped to ``low``.\n@@ -100,7 +93,3 @@\n     The maximum value of the range to map into the palette. Values above\n     this are clamped to ``high``.\n     \"\"\")\n-\n-    def __init__(self, palette=None, **kwargs):\n-        if palette is not None: kwargs['palette'] = palette\n-        super(LogColorMapper, self).__init__(**kwargs)\n", "issue": "Updating of image ColorMapper\nThe ability to change the low/high of a ColorMapper for an already existing image (adjusting contrast/brightness) through widget callbacks on a server is desired. I could imagine this being accomplished by the following code, which incidentally doesn't throw any errors as is, it just doesn't do anything ;)\n\n```\nimport numpy as np\nfrom bokeh.plotting import figure, curdoc\nfrom bokeh.layouts import row, layout\nfrom bokeh.models import Slider\nfrom bokeh.models.mappers import LinearColorMapper\nfrom bokeh.palettes import Greys9\n\ndef change_image_contrast(attr, old, new):\n    fig_im.glyph.color_mapper.update(low=graph_min_slider.value, high=graph_max_slider.value)\n    fig_im.trigger('glyph', fig_im.glyph, fig_im.glyph)\n\ngraph_min_slider = Slider(title=\"Min\", start=0, end=99, step=1, value=0)\ngraph_max_slider = Slider(title=\"Max\", start=1, end=100, step=1, value=100)\n\ngraph_min_slider.on_change('value', change_image_contrast)\ngraph_max_slider.on_change('value', change_image_contrast)\n\nfig = figure(plot_width=500, plot_height=500, x_range=(0, 10), y_range=(0, 10))\n\nfig_im = fig.image(image=[np.random.randint(0, 100, (10, 10), dtype='int16')], x=[0], y=[0], dw=[10], dh=[10],\n                   color_mapper=LinearColorMapper(low=0, high=100, palette=Greys9))\n\ncurdoc().add_root(layout([fig], [row([graph_min_slider, graph_max_slider])]))\n```\n\n", "before_files": [{"content": "\"\"\" Models for mapping values from one range or space to another.\n\n\"\"\"\nfrom __future__ import absolute_import\n\nfrom ..model import Model\nfrom ..core.properties import abstract\nfrom ..core.properties import Float, Color, Enum, Seq\nfrom ..core.enums import Palette\nfrom .. import palettes\n\n@abstract\nclass ColorMapper(Model):\n    \"\"\" Base class for color mapper types. `ColorMapper`` is not\n    generally useful to instantiate on its own.\n\n    \"\"\"\n\nclass LinearColorMapper(ColorMapper):\n    \"\"\" Map numbers in a range [*low*, *high*] linearly into a\n    sequence of colors (a palette).\n\n    For example, if the range is [0, 99] and the palette is\n    ``['red', 'green', 'blue']``, the values would be mapped as\n    follows::\n\n             x < 0  : 'red'     # values < low are clamped\n        0 >= x < 33 : 'red'\n       33 >= x < 66 : 'green'\n       66 >= x < 99 : 'blue'\n       99 >= x      : 'blue'    # values > high are clamped\n\n    \"\"\"\n\n    palette = Seq(Color, help=\"\"\"\n    A sequence of colors to use as the target palette for mapping.\n\n    This property can also be set as a ``String``, to the name of\n    any of the palettes shown in :ref:`bokeh.palettes`.\n    \"\"\").accepts(Enum(Palette), lambda pal: getattr(palettes, pal))\n\n    low = Float(help=\"\"\"\n    The minimum value of the range to map into the palette. Values below\n    this are clamped to ``low``.\n    \"\"\")\n\n    high = Float(help=\"\"\"\n    The maximum value of the range to map into the palette. Values above\n    this are clamped to ``high``.\n    \"\"\")\n\n    # TODO: (jc) what is the color code for transparent?\n    # TODO: (bev) better docstring\n    reserve_color = Color(\"#ffffff\", help=\"\"\"\n    Used by Abstract Rendering.\n    \"\"\")\n\n    # TODO: (bev) better docstring\n    reserve_val = Float(default=None, help=\"\"\"\n    Used by Abstract Rendering.\n    \"\"\")\n\n    def __init__(self, palette=None, **kwargs):\n        if palette is not None: kwargs['palette'] = palette\n        super(LinearColorMapper, self).__init__(**kwargs)\n\nclass LogColorMapper(ColorMapper):\n    \"\"\" Map numbers in a range [*low*, *high*] into a\n    sequence of colors (a palette) on a natural logarithm scale.\n\n    For example, if the range is [0, 25] and the palette is\n    ``['red', 'green', 'blue']``, the values would be mapped as\n    follows::\n\n                x < 0     : 'red'     # values < low are clamped\n       0     >= x < 2.72  : 'red'     # math.e ** 1\n       2.72  >= x < 7.39  : 'green'   # math.e ** 2\n       7.39  >= x < 20.09 : 'blue'    # math.e ** 3\n       20.09 >= x         : 'blue'    # values > high are clamped\n\n    .. warning::\n        The LogColorMapper only works for images with scalar values that are\n        non-negative.\n\n    \"\"\"\n\n    palette = Seq(Color, help=\"\"\"\n    A sequence of colors to use as the target palette for mapping.\n\n    This property can also be set as a ``String``, to the name of\n    any of the palettes shown in :ref:`bokeh.palettes`.\n    \"\"\").accepts(Enum(Palette), lambda pal: getattr(palettes, pal))\n\n    low = Float(help=\"\"\"\n    The minimum value of the range to map into the palette. Values below\n    this are clamped to ``low``.\n    \"\"\")\n\n    high = Float(help=\"\"\"\n    The maximum value of the range to map into the palette. Values above\n    this are clamped to ``high``.\n    \"\"\")\n\n    def __init__(self, palette=None, **kwargs):\n        if palette is not None: kwargs['palette'] = palette\n        super(LogColorMapper, self).__init__(**kwargs)\n", "path": "bokeh/models/mappers.py"}], "after_files": [{"content": "\"\"\" Models for mapping values from one range or space to another.\n\n\"\"\"\nfrom __future__ import absolute_import\n\nfrom ..model import Model\nfrom ..core.properties import abstract\nfrom ..core.properties import Float, Color, Enum, Seq\nfrom ..core.enums import Palette\nfrom .. import palettes\n\n@abstract\nclass ColorMapper(Model):\n    \"\"\" Base class for color mapper types. `ColorMapper`` is not\n    generally useful to instantiate on its own.\n\n    \"\"\"\n\n    palette = Seq(Color, help=\"\"\"\n    A sequence of colors to use as the target palette for mapping.\n\n    This property can also be set as a ``String``, to the name of\n    any of the palettes shown in :ref:`bokeh.palettes`.\n    \"\"\").accepts(Enum(Palette), lambda pal: getattr(palettes, pal))\n\n    def __init__(self, palette=None, **kwargs):\n        if palette is not None: kwargs['palette'] = palette\n        super(ColorMapper, self).__init__(**kwargs)\n\nclass LinearColorMapper(ColorMapper):\n    \"\"\" Map numbers in a range [*low*, *high*] linearly into a\n    sequence of colors (a palette).\n\n    For example, if the range is [0, 99] and the palette is\n    ``['red', 'green', 'blue']``, the values would be mapped as\n    follows::\n\n             x < 0  : 'red'     # values < low are clamped\n        0 >= x < 33 : 'red'\n       33 >= x < 66 : 'green'\n       66 >= x < 99 : 'blue'\n       99 >= x      : 'blue'    # values > high are clamped\n\n    \"\"\"\n\n    low = Float(help=\"\"\"\n    The minimum value of the range to map into the palette. Values below\n    this are clamped to ``low``.\n    \"\"\")\n\n    high = Float(help=\"\"\"\n    The maximum value of the range to map into the palette. Values above\n    this are clamped to ``high``.\n    \"\"\")\n\n    # TODO: (jc) what is the color code for transparent?\n    # TODO: (bev) better docstring\n    reserve_color = Color(\"#ffffff\", help=\"\"\"\n    Used by Abstract Rendering.\n    \"\"\")\n\n    # TODO: (bev) better docstring\n    reserve_val = Float(default=None, help=\"\"\"\n    Used by Abstract Rendering.\n    \"\"\")\n\nclass LogColorMapper(ColorMapper):\n    \"\"\" Map numbers in a range [*low*, *high*] into a\n    sequence of colors (a palette) on a natural logarithm scale.\n\n    For example, if the range is [0, 25] and the palette is\n    ``['red', 'green', 'blue']``, the values would be mapped as\n    follows::\n\n                x < 0     : 'red'     # values < low are clamped\n       0     >= x < 2.72  : 'red'     # math.e ** 1\n       2.72  >= x < 7.39  : 'green'   # math.e ** 2\n       7.39  >= x < 20.09 : 'blue'    # math.e ** 3\n       20.09 >= x         : 'blue'    # values > high are clamped\n\n    .. warning::\n        The LogColorMapper only works for images with scalar values that are\n        non-negative.\n\n    \"\"\"\n\n    low = Float(help=\"\"\"\n    The minimum value of the range to map into the palette. Values below\n    this are clamped to ``low``.\n    \"\"\")\n\n    high = Float(help=\"\"\"\n    The maximum value of the range to map into the palette. Values above\n    this are clamped to ``high``.\n    \"\"\")\n", "path": "bokeh/models/mappers.py"}]}