prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  broken match histograms gallery example
  ## Description
  
  This bug was reported here: https://forum.image.sc/t/exposure-match-histograms-broken/61682
  
  Most likely this is due to some unintended change in scaling that was introduced when adding the float32 support, so hopefully it is an easy fix. I can take a look soon.
  
  ## Way to reproduce
  
  Run the following demo with v0.19.0 or v0.19.1: https://scikit-image.org/docs/stable/auto_examples/color_exposure/plot_histogram_matching.html#sphx-glr-auto-examples-color-exposure-plot-histogram-matching-py
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `skimage/exposure/histogram_matching.py`
  Content:
  ```
  1 import numpy as np
  2 
  3 from .._shared import utils
  4 
  5 
  6 def _match_cumulative_cdf(source, template):
  7     """
  8     Return modified source array so that the cumulative density function of
  9     its values matches the cumulative density function of the template.
  10     """
  11     src_values, src_unique_indices, src_counts = np.unique(source.ravel(),
  12                                                            return_inverse=True,
  13                                                            return_counts=True)
  14     tmpl_values, tmpl_counts = np.unique(template.ravel(), return_counts=True)
  15 
  16     # calculate normalized quantiles for each array
  17     src_quantiles = np.cumsum(src_counts) / source.size
  18     tmpl_quantiles = np.cumsum(tmpl_counts) / template.size
  19 
  20     interp_a_values = np.interp(src_quantiles, tmpl_quantiles, tmpl_values)
  21     return interp_a_values[src_unique_indices].reshape(source.shape)
  22 
  23 
  24 @utils.channel_as_last_axis(channel_arg_positions=(0, 1))
  25 @utils.deprecate_multichannel_kwarg()
  26 def match_histograms(image, reference, *, channel_axis=None,
  27                      multichannel=False):
  28     """Adjust an image so that its cumulative histogram matches that of another.
  29 
  30     The adjustment is applied separately for each channel.
  31 
  32     Parameters
  33     ----------
  34     image : ndarray
  35         Input image. Can be gray-scale or in color.
  36     reference : ndarray
  37         Image to match histogram of. Must have the same number of channels as
  38         image.
  39     channel_axis : int or None, optional
  40         If None, the image is assumed to be a grayscale (single channel) image.
  41         Otherwise, this parameter indicates which axis of the array corresponds
  42         to channels.
  43     multichannel : bool, optional
  44         Apply the matching separately for each channel. This argument is
  45         deprecated: specify `channel_axis` instead.
  46 
  47     Returns
  48     -------
  49     matched : ndarray
  50         Transformed input image.
  51 
  52     Raises
  53     ------
  54     ValueError
  55         Thrown when the number of channels in the input image and the reference
  56         differ.
  57 
  58     References
  59     ----------
  60     .. [1] http://paulbourke.net/miscellaneous/equalisation/
  61 
  62     """
  63     if image.ndim != reference.ndim:
  64         raise ValueError('Image and reference must have the same number '
  65                          'of channels.')
  66     out_dtype = utils._supported_float_type(image.dtype)
  67 
  68     if channel_axis is not None:
  69         if image.shape[-1] != reference.shape[-1]:
  70             raise ValueError('Number of channels in the input image and '
  71                              'reference image must match!')
  72 
  73         matched = np.empty(image.shape, dtype=image.dtype)
  74         for channel in range(image.shape[-1]):
  75             matched_channel = _match_cumulative_cdf(image[..., channel],
  76                                                     reference[..., channel])
  77             matched[..., channel] = matched_channel
  78     else:
  79         # _match_cumulative_cdf will always return float64 due to np.interp
  80         matched = _match_cumulative_cdf(image, reference)
  81 
  82     return matched.astype(out_dtype, copy=False)
  83
  ```
  --- 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/skimage/exposure/histogram_matching.py b/skimage/exposure/histogram_matching.py
  --- a/skimage/exposure/histogram_matching.py
  +++ b/skimage/exposure/histogram_matching.py
  @@ -63,7 +63,6 @@
       if image.ndim != reference.ndim:
           raise ValueError('Image and reference must have the same number '
                            'of channels.')
  -    out_dtype = utils._supported_float_type(image.dtype)
   
       if channel_axis is not None:
           if image.shape[-1] != reference.shape[-1]:
  @@ -79,4 +78,8 @@
           # _match_cumulative_cdf will always return float64 due to np.interp
           matched = _match_cumulative_cdf(image, reference)
   
  -    return matched.astype(out_dtype, copy=False)
  +    if matched.dtype.kind == 'f':
  +        # output a float32 result when the input is float16 or float32
  +        out_dtype = utils._supported_float_type(image.dtype)
  +        matched = matched.astype(out_dtype, copy=False)
  +    return matched
  
verification_info: {"golden_diff": "diff --git a/skimage/exposure/histogram_matching.py b/skimage/exposure/histogram_matching.py\n--- a/skimage/exposure/histogram_matching.py\n+++ b/skimage/exposure/histogram_matching.py\n@@ -63,7 +63,6 @@\n     if image.ndim != reference.ndim:\n         raise ValueError('Image and reference must have the same number '\n                          'of channels.')\n-    out_dtype = utils._supported_float_type(image.dtype)\n \n     if channel_axis is not None:\n         if image.shape[-1] != reference.shape[-1]:\n@@ -79,4 +78,8 @@\n         # _match_cumulative_cdf will always return float64 due to np.interp\n         matched = _match_cumulative_cdf(image, reference)\n \n-    return matched.astype(out_dtype, copy=False)\n+    if matched.dtype.kind == 'f':\n+        # output a float32 result when the input is float16 or float32\n+        out_dtype = utils._supported_float_type(image.dtype)\n+        matched = matched.astype(out_dtype, copy=False)\n+    return matched\n", "issue": "broken match histograms gallery example\n## Description\r\n\r\nThis bug was reported here: https://forum.image.sc/t/exposure-match-histograms-broken/61682\r\n\r\nMost likely this is due to some unintended change in scaling that was introduced when adding the float32 support, so hopefully it is an easy fix. I can take a look soon.\r\n\r\n## Way to reproduce\r\n\r\nRun the following demo with v0.19.0 or v0.19.1: https://scikit-image.org/docs/stable/auto_examples/color_exposure/plot_histogram_matching.html#sphx-glr-auto-examples-color-exposure-plot-histogram-matching-py\r\n\n", "before_files": [{"content": "import numpy as np\n\nfrom .._shared import utils\n\n\ndef _match_cumulative_cdf(source, template):\n    \"\"\"\n    Return modified source array so that the cumulative density function of\n    its values matches the cumulative density function of the template.\n    \"\"\"\n    src_values, src_unique_indices, src_counts = np.unique(source.ravel(),\n                                                           return_inverse=True,\n                                                           return_counts=True)\n    tmpl_values, tmpl_counts = np.unique(template.ravel(), return_counts=True)\n\n    # calculate normalized quantiles for each array\n    src_quantiles = np.cumsum(src_counts) / source.size\n    tmpl_quantiles = np.cumsum(tmpl_counts) / template.size\n\n    interp_a_values = np.interp(src_quantiles, tmpl_quantiles, tmpl_values)\n    return interp_a_values[src_unique_indices].reshape(source.shape)\n\n\n@utils.channel_as_last_axis(channel_arg_positions=(0, 1))\n@utils.deprecate_multichannel_kwarg()\ndef match_histograms(image, reference, *, channel_axis=None,\n                     multichannel=False):\n    \"\"\"Adjust an image so that its cumulative histogram matches that of another.\n\n    The adjustment is applied separately for each channel.\n\n    Parameters\n    ----------\n    image : ndarray\n        Input image. Can be gray-scale or in color.\n    reference : ndarray\n        Image to match histogram of. Must have the same number of channels as\n        image.\n    channel_axis : int or None, optional\n        If None, the image is assumed to be a grayscale (single channel) image.\n        Otherwise, this parameter indicates which axis of the array corresponds\n        to channels.\n    multichannel : bool, optional\n        Apply the matching separately for each channel. This argument is\n        deprecated: specify `channel_axis` instead.\n\n    Returns\n    -------\n    matched : ndarray\n        Transformed input image.\n\n    Raises\n    ------\n    ValueError\n        Thrown when the number of channels in the input image and the reference\n        differ.\n\n    References\n    ----------\n    .. [1] http://paulbourke.net/miscellaneous/equalisation/\n\n    \"\"\"\n    if image.ndim != reference.ndim:\n        raise ValueError('Image and reference must have the same number '\n                         'of channels.')\n    out_dtype = utils._supported_float_type(image.dtype)\n\n    if channel_axis is not None:\n        if image.shape[-1] != reference.shape[-1]:\n            raise ValueError('Number of channels in the input image and '\n                             'reference image must match!')\n\n        matched = np.empty(image.shape, dtype=image.dtype)\n        for channel in range(image.shape[-1]):\n            matched_channel = _match_cumulative_cdf(image[..., channel],\n                                                    reference[..., channel])\n            matched[..., channel] = matched_channel\n    else:\n        # _match_cumulative_cdf will always return float64 due to np.interp\n        matched = _match_cumulative_cdf(image, reference)\n\n    return matched.astype(out_dtype, copy=False)\n", "path": "skimage/exposure/histogram_matching.py"}], "after_files": [{"content": "import numpy as np\n\nfrom .._shared import utils\n\n\ndef _match_cumulative_cdf(source, template):\n    \"\"\"\n    Return modified source array so that the cumulative density function of\n    its values matches the cumulative density function of the template.\n    \"\"\"\n    src_values, src_unique_indices, src_counts = np.unique(source.ravel(),\n                                                           return_inverse=True,\n                                                           return_counts=True)\n    tmpl_values, tmpl_counts = np.unique(template.ravel(), return_counts=True)\n\n    # calculate normalized quantiles for each array\n    src_quantiles = np.cumsum(src_counts) / source.size\n    tmpl_quantiles = np.cumsum(tmpl_counts) / template.size\n\n    interp_a_values = np.interp(src_quantiles, tmpl_quantiles, tmpl_values)\n    return interp_a_values[src_unique_indices].reshape(source.shape)\n\n\n@utils.channel_as_last_axis(channel_arg_positions=(0, 1))\n@utils.deprecate_multichannel_kwarg()\ndef match_histograms(image, reference, *, channel_axis=None,\n                     multichannel=False):\n    \"\"\"Adjust an image so that its cumulative histogram matches that of another.\n\n    The adjustment is applied separately for each channel.\n\n    Parameters\n    ----------\n    image : ndarray\n        Input image. Can be gray-scale or in color.\n    reference : ndarray\n        Image to match histogram of. Must have the same number of channels as\n        image.\n    channel_axis : int or None, optional\n        If None, the image is assumed to be a grayscale (single channel) image.\n        Otherwise, this parameter indicates which axis of the array corresponds\n        to channels.\n    multichannel : bool, optional\n        Apply the matching separately for each channel. This argument is\n        deprecated: specify `channel_axis` instead.\n\n    Returns\n    -------\n    matched : ndarray\n        Transformed input image.\n\n    Raises\n    ------\n    ValueError\n        Thrown when the number of channels in the input image and the reference\n        differ.\n\n    References\n    ----------\n    .. [1] http://paulbourke.net/miscellaneous/equalisation/\n\n    \"\"\"\n    if image.ndim != reference.ndim:\n        raise ValueError('Image and reference must have the same number '\n                         'of channels.')\n\n    if channel_axis is not None:\n        if image.shape[-1] != reference.shape[-1]:\n            raise ValueError('Number of channels in the input image and '\n                             'reference image must match!')\n\n        matched = np.empty(image.shape, dtype=image.dtype)\n        for channel in range(image.shape[-1]):\n            matched_channel = _match_cumulative_cdf(image[..., channel],\n                                                    reference[..., channel])\n            matched[..., channel] = matched_channel\n    else:\n        # _match_cumulative_cdf will always return float64 due to np.interp\n        matched = _match_cumulative_cdf(image, reference)\n\n    if matched.dtype.kind == 'f':\n        # output a float32 result when the input is float16 or float32\n        out_dtype = utils._supported_float_type(image.dtype)\n        matched = matched.astype(out_dtype, copy=False)\n    return matched\n", "path": "skimage/exposure/histogram_matching.py"}]}