We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Interpolation error in measure.profile_line
## Description

#4206, once merged, exposes interesting behavior for [measure.profile_line](https://scikit-image.org/docs/dev/api/skimage.measure.html#skimage.measure.profile_line). Consider

```python
image = np.arange(12).reshape(4, 3)
# reduce_func is a new parameter proposed in #4206
prof = profile_line(image, (0, 1), (3, 1), linewidth=3, reduce_func=None)
assert_array_equal(image, prof)
```
As I understand it, the returned profile should be identical with the original image but we get this (value at (0, 2) is different):
```
AssertionError: 
Arrays are not equal
Mismatch: 8.33%
Max absolute difference: 2
Max relative difference: 0.
 x: array([[ 0,  1,  2],
       [ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11]])
 y: array([[ 0,  1,  0],
       [ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11]])
```
This might originate in [scipy.ndimage.map_coordinates](https://docs.scipy.org/doc/scipy/reference/generated/scipy.ndimage.map_coordinates.html#scipy.ndimage.map_coordinates). Looks like a potential bug to me but might be an edge case for the underlying interpolation that can be ignored/is not reasonable to fix. 
This behavior is already relevant even before merging #4206 because the faulty value will change the mean value of the profile line.

https://github.com/scikit-image/scikit-image/pull/4206#issuecomment-544920806 also highlights additional strange behavior.

## Version information

Current master, exposed once #4206 is merged.


--- 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/measure/profile.py`
Content:
```
1 from warnings import warn
2 import numpy as np
3 from scipy import ndimage as ndi
4 
5 
6 def profile_line(image, src, dst, linewidth=1,
7                  order=None, mode='constant', cval=0.0,
8                  *, reduce_func=np.mean):
9     """Return the intensity profile of an image measured along a scan line.
10 
11     Parameters
12     ----------
13     image : numeric array, shape (M, N[, C])
14         The image, either grayscale (2D array) or multichannel
15         (3D array, where the final axis contains the channel
16         information).
17     src : 2-tuple of numeric scalar (float or int)
18         The start point of the scan line.
19     dst : 2-tuple of numeric scalar (float or int)
20         The end point of the scan line. The destination point is *included*
21         in the profile, in contrast to standard numpy indexing.
22     linewidth : int, optional
23         Width of the scan, perpendicular to the line
24     order : int in {0, 1, 2, 3, 4, 5}, optional
25         The order of the spline interpolation, default is 0 if
26         image.dtype is bool and 1 otherwise. The order has to be in
27         the range 0-5. See `skimage.transform.warp` for detail.
28     mode : {'constant', 'nearest', 'reflect', 'mirror', 'wrap'}, optional
29         How to compute any values falling outside of the image.
30     cval : float, optional
31         If `mode` is 'constant', what constant value to use outside the image.
32     reduce_func : callable, optional
33         Function used to calculate the aggregation of pixel values
34         perpendicular to the profile_line direction when `linewidth` > 1.
35         If set to None the unreduced array will be returned.
36 
37     Returns
38     -------
39     return_value : array
40         The intensity profile along the scan line. The length of the profile
41         is the ceil of the computed length of the scan line.
42 
43     Examples
44     --------
45     >>> x = np.array([[1, 1, 1, 2, 2, 2]])
46     >>> img = np.vstack([np.zeros_like(x), x, x, x, np.zeros_like(x)])
47     >>> img
48     array([[0, 0, 0, 0, 0, 0],
49            [1, 1, 1, 2, 2, 2],
50            [1, 1, 1, 2, 2, 2],
51            [1, 1, 1, 2, 2, 2],
52            [0, 0, 0, 0, 0, 0]])
53     >>> profile_line(img, (2, 1), (2, 4))
54     array([1., 1., 2., 2.])
55     >>> profile_line(img, (1, 0), (1, 6), cval=4)
56     array([1., 1., 1., 2., 2., 2., 4.])
57 
58     The destination point is included in the profile, in contrast to
59     standard numpy indexing.
60     For example:
61 
62     >>> profile_line(img, (1, 0), (1, 6))  # The final point is out of bounds
63     array([1., 1., 1., 2., 2., 2., 0.])
64     >>> profile_line(img, (1, 0), (1, 5))  # This accesses the full first row
65     array([1., 1., 1., 2., 2., 2.])
66 
67     For different reduce_func inputs:
68 
69     >>> profile_line(img, (1, 0), (1, 3), linewidth=3, reduce_func=np.mean)
70     array([0.66666667, 0.66666667, 0.66666667, 1.33333333])
71     >>> profile_line(img, (1, 0), (1, 3), linewidth=3, reduce_func=np.max)
72     array([1, 1, 1, 2])
73     >>> profile_line(img, (1, 0), (1, 3), linewidth=3, reduce_func=np.sum)
74     array([2, 2, 2, 4])
75 
76     The unreduced array will be returned when `reduce_func` is None or when
77     `reduce_func` acts on each pixel value individually.
78 
79     >>> profile_line(img, (1, 2), (4, 2), linewidth=3, order=0,
80     ...     reduce_func=None)
81     array([[1, 1, 2],
82            [1, 1, 2],
83            [1, 1, 2],
84            [0, 0, 0]])
85     >>> profile_line(img, (1, 0), (1, 3), linewidth=3, reduce_func=np.sqrt)
86     array([[1.        , 1.        , 0.        ],
87            [1.        , 1.        , 0.        ],
88            [1.        , 1.        , 0.        ],
89            [1.41421356, 1.41421356, 0.        ]])
90     """
91     if order is None:
92         order = 0 if image.dtype == bool else 1
93 
94     if image.dtype == bool and order != 0:
95         warn("Input image dtype is bool. Interpolation is not defined "
96              "with bool data type. Please set order to 0 or explicitely "
97              "cast input image to another data type. Starting from version "
98              "0.19 a ValueError will be raised instead of this warning.",
99              FutureWarning, stacklevel=2)
100 
101     perp_lines = _line_profile_coordinates(src, dst, linewidth=linewidth)
102     if image.ndim == 3:
103         pixels = [ndi.map_coordinates(image[..., i], perp_lines,
104                                       prefilter=order > 1,
105                                       order=order, mode=mode,
106                                       cval=cval) for i in
107                   range(image.shape[2])]
108         pixels = np.transpose(np.asarray(pixels), (1, 2, 0))
109     else:
110         pixels = ndi.map_coordinates(image, perp_lines, prefilter=order > 1,
111                                      order=order, mode=mode, cval=cval)
112     # The outputted array with reduce_func=None gives an array where the
113     # row values (axis=1) are flipped. Here, we make this consistent.
114     pixels = np.flip(pixels, axis=1)
115 
116     if reduce_func is None:
117         intensities = pixels
118     else:
119         try:
120             intensities = reduce_func(pixels, axis=1)
121         except TypeError:  # function doesn't allow axis kwarg
122             intensities = np.apply_along_axis(reduce_func, arr=pixels, axis=1)
123 
124     return intensities
125 
126 
127 def _line_profile_coordinates(src, dst, linewidth=1):
128     """Return the coordinates of the profile of an image along a scan line.
129 
130     Parameters
131     ----------
132     src : 2-tuple of numeric scalar (float or int)
133         The start point of the scan line.
134     dst : 2-tuple of numeric scalar (float or int)
135         The end point of the scan line.
136     linewidth : int, optional
137         Width of the scan, perpendicular to the line
138 
139     Returns
140     -------
141     coords : array, shape (2, N, C), float
142         The coordinates of the profile along the scan line. The length of the
143         profile is the ceil of the computed length of the scan line.
144 
145     Notes
146     -----
147     This is a utility method meant to be used internally by skimage functions.
148     The destination point is included in the profile, in contrast to
149     standard numpy indexing.
150     """
151     src_row, src_col = src = np.asarray(src, dtype=float)
152     dst_row, dst_col = dst = np.asarray(dst, dtype=float)
153     d_row, d_col = dst - src
154     theta = np.arctan2(d_row, d_col)
155 
156     length = int(np.ceil(np.hypot(d_row, d_col) + 1))
157     # we add one above because we include the last point in the profile
158     # (in contrast to standard numpy indexing)
159     line_col = np.linspace(src_col, dst_col, length)
160     line_row = np.linspace(src_row, dst_row, length)
161 
162     # we subtract 1 from linewidth to change from pixel-counting
163     # (make this line 3 pixels wide) to point distances (the
164     # distance between pixel centers)
165     col_width = (linewidth - 1) * np.sin(-theta) / 2
166     row_width = (linewidth - 1) * np.cos(theta) / 2
167     perp_rows = np.array([np.linspace(row_i - row_width, row_i + row_width,
168                                       linewidth) for row_i in line_row])
169     perp_cols = np.array([np.linspace(col_i - col_width, col_i + col_width,
170                                       linewidth) for col_i in line_col])
171     return np.array([perp_rows, perp_cols])
172
```
--- 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()

```

diff --git a/skimage/measure/profile.py b/skimage/measure/profile.py
--- a/skimage/measure/profile.py
+++ b/skimage/measure/profile.py
@@ -4,21 +4,22 @@
 
 
 def profile_line(image, src, dst, linewidth=1,
-                 order=None, mode='constant', cval=0.0,
+                 order=None, mode=None, cval=0.0,
                  *, reduce_func=np.mean):
     """Return the intensity profile of an image measured along a scan line.
 
     Parameters
     ----------
-    image : numeric array, shape (M, N[, C])
+    image : ndarray, shape (M, N[, C])
         The image, either grayscale (2D array) or multichannel
         (3D array, where the final axis contains the channel
         information).
-    src : 2-tuple of numeric scalar (float or int)
-        The start point of the scan line.
-    dst : 2-tuple of numeric scalar (float or int)
-        The end point of the scan line. The destination point is *included*
-        in the profile, in contrast to standard numpy indexing.
+    src : array_like, shape (2, )
+        The coordinates of the start point of the scan line.
+    dst : array_like, shape (2, )
+        The coordinates of the end point of the scan
+        line. The destination point is *included* in the profile, in
+        contrast to standard numpy indexing.
     linewidth : int, optional
         Width of the scan, perpendicular to the line
     order : int in {0, 1, 2, 3, 4, 5}, optional
@@ -97,6 +98,12 @@
              "cast input image to another data type. Starting from version "
              "0.19 a ValueError will be raised instead of this warning.",
              FutureWarning, stacklevel=2)
+    if mode is None:
+        warn("Default out of bounds interpolation mode 'constant' is "
+             "deprecated. In version 0.19 it will be set to 'reflect'. "
+             "To avoid this warning, set `mode=` explicitly.",
+             FutureWarning, stacklevel=2)
+        mode = 'constant'
 
     perp_lines = _line_profile_coordinates(src, dst, linewidth=linewidth)
     if image.ndim == 3:

{"golden_diff": "diff --git a/skimage/measure/profile.py b/skimage/measure/profile.py\n--- a/skimage/measure/profile.py\n+++ b/skimage/measure/profile.py\n@@ -4,21 +4,22 @@\n \n \n def profile_line(image, src, dst, linewidth=1,\n-                 order=None, mode='constant', cval=0.0,\n+                 order=None, mode=None, cval=0.0,\n                  *, reduce_func=np.mean):\n     \"\"\"Return the intensity profile of an image measured along a scan line.\n \n     Parameters\n     ----------\n-    image : numeric array, shape (M, N[, C])\n+    image : ndarray, shape (M, N[, C])\n         The image, either grayscale (2D array) or multichannel\n         (3D array, where the final axis contains the channel\n         information).\n-    src : 2-tuple of numeric scalar (float or int)\n-        The start point of the scan line.\n-    dst : 2-tuple of numeric scalar (float or int)\n-        The end point of the scan line. The destination point is *included*\n-        in the profile, in contrast to standard numpy indexing.\n+    src : array_like, shape (2, )\n+        The coordinates of the start point of the scan line.\n+    dst : array_like, shape (2, )\n+        The coordinates of the end point of the scan\n+        line. The destination point is *included* in the profile, in\n+        contrast to standard numpy indexing.\n     linewidth : int, optional\n         Width of the scan, perpendicular to the line\n     order : int in {0, 1, 2, 3, 4, 5}, optional\n@@ -97,6 +98,12 @@\n              \"cast input image to another data type. Starting from version \"\n              \"0.19 a ValueError will be raised instead of this warning.\",\n              FutureWarning, stacklevel=2)\n+    if mode is None:\n+        warn(\"Default out of bounds interpolation mode 'constant' is \"\n+             \"deprecated. In version 0.19 it will be set to 'reflect'. \"\n+             \"To avoid this warning, set `mode=` explicitly.\",\n+             FutureWarning, stacklevel=2)\n+        mode = 'constant'\n \n     perp_lines = _line_profile_coordinates(src, dst, linewidth=linewidth)\n     if image.ndim == 3:\n", "issue": "Interpolation error in measure.profile_line\n## Description\r\n\r\n#4206, once merged, exposes interesting behavior for [measure.profile_line](https://scikit-image.org/docs/dev/api/skimage.measure.html#skimage.measure.profile_line). Consider\r\n\r\n```python\r\nimage = np.arange(12).reshape(4, 3)\r\n# reduce_func is a new parameter proposed in #4206\r\nprof = profile_line(image, (0, 1), (3, 1), linewidth=3, reduce_func=None)\r\nassert_array_equal(image, prof)\r\n```\r\nAs I understand it, the returned profile should be identical with the original image but we get this (value at (0, 2) is different):\r\n```\r\nAssertionError: \r\nArrays are not equal\r\nMismatch: 8.33%\r\nMax absolute difference: 2\r\nMax relative difference: 0.\r\n x: array([[ 0,  1,  2],\r\n       [ 3,  4,  5],\r\n       [ 6,  7,  8],\r\n       [ 9, 10, 11]])\r\n y: array([[ 0,  1,  0],\r\n       [ 3,  4,  5],\r\n       [ 6,  7,  8],\r\n       [ 9, 10, 11]])\r\n```\r\nThis might originate in [scipy.ndimage.map_coordinates](https://docs.scipy.org/doc/scipy/reference/generated/scipy.ndimage.map_coordinates.html#scipy.ndimage.map_coordinates). Looks like a potential bug to me but might be an edge case for the underlying interpolation that can be ignored/is not reasonable to fix. \r\nThis behavior is already relevant even before merging #4206 because the faulty value will change the mean value of the profile line.\r\n\r\nhttps://github.com/scikit-image/scikit-image/pull/4206#issuecomment-544920806 also highlights additional strange behavior.\r\n\r\n## Version information\r\n\r\nCurrent master, exposed once #4206 is merged.\r\n\n", "before_files": [{"content": "from warnings import warn\nimport numpy as np\nfrom scipy import ndimage as ndi\n\n\ndef profile_line(image, src, dst, linewidth=1,\n                 order=None, mode='constant', cval=0.0,\n                 *, reduce_func=np.mean):\n    \"\"\"Return the intensity profile of an image measured along a scan line.\n\n    Parameters\n    ----------\n    image : numeric array, shape (M, N[, C])\n        The image, either grayscale (2D array) or multichannel\n        (3D array, where the final axis contains the channel\n        information).\n    src : 2-tuple of numeric scalar (float or int)\n        The start point of the scan line.\n    dst : 2-tuple of numeric scalar (float or int)\n        The end point of the scan line. The destination point is *included*\n        in the profile, in contrast to standard numpy indexing.\n    linewidth : int, optional\n        Width of the scan, perpendicular to the line\n    order : int in {0, 1, 2, 3, 4, 5}, optional\n        The order of the spline interpolation, default is 0 if\n        image.dtype is bool and 1 otherwise. The order has to be in\n        the range 0-5. See `skimage.transform.warp` for detail.\n    mode : {'constant', 'nearest', 'reflect', 'mirror', 'wrap'}, optional\n        How to compute any values falling outside of the image.\n    cval : float, optional\n        If `mode` is 'constant', what constant value to use outside the image.\n    reduce_func : callable, optional\n        Function used to calculate the aggregation of pixel values\n        perpendicular to the profile_line direction when `linewidth` > 1.\n        If set to None the unreduced array will be returned.\n\n    Returns\n    -------\n    return_value : array\n        The intensity profile along the scan line. The length of the profile\n        is the ceil of the computed length of the scan line.\n\n    Examples\n    --------\n    >>> x = np.array([[1, 1, 1, 2, 2, 2]])\n    >>> img = np.vstack([np.zeros_like(x), x, x, x, np.zeros_like(x)])\n    >>> img\n    array([[0, 0, 0, 0, 0, 0],\n           [1, 1, 1, 2, 2, 2],\n           [1, 1, 1, 2, 2, 2],\n           [1, 1, 1, 2, 2, 2],\n           [0, 0, 0, 0, 0, 0]])\n    >>> profile_line(img, (2, 1), (2, 4))\n    array([1., 1., 2., 2.])\n    >>> profile_line(img, (1, 0), (1, 6), cval=4)\n    array([1., 1., 1., 2., 2., 2., 4.])\n\n    The destination point is included in the profile, in contrast to\n    standard numpy indexing.\n    For example:\n\n    >>> profile_line(img, (1, 0), (1, 6))  # The final point is out of bounds\n    array([1., 1., 1., 2., 2., 2., 0.])\n    >>> profile_line(img, (1, 0), (1, 5))  # This accesses the full first row\n    array([1., 1., 1., 2., 2., 2.])\n\n    For different reduce_func inputs:\n\n    >>> profile_line(img, (1, 0), (1, 3), linewidth=3, reduce_func=np.mean)\n    array([0.66666667, 0.66666667, 0.66666667, 1.33333333])\n    >>> profile_line(img, (1, 0), (1, 3), linewidth=3, reduce_func=np.max)\n    array([1, 1, 1, 2])\n    >>> profile_line(img, (1, 0), (1, 3), linewidth=3, reduce_func=np.sum)\n    array([2, 2, 2, 4])\n\n    The unreduced array will be returned when `reduce_func` is None or when\n    `reduce_func` acts on each pixel value individually.\n\n    >>> profile_line(img, (1, 2), (4, 2), linewidth=3, order=0,\n    ...     reduce_func=None)\n    array([[1, 1, 2],\n           [1, 1, 2],\n           [1, 1, 2],\n           [0, 0, 0]])\n    >>> profile_line(img, (1, 0), (1, 3), linewidth=3, reduce_func=np.sqrt)\n    array([[1.        , 1.        , 0.        ],\n           [1.        , 1.        , 0.        ],\n           [1.        , 1.        , 0.        ],\n           [1.41421356, 1.41421356, 0.        ]])\n    \"\"\"\n    if order is None:\n        order = 0 if image.dtype == bool else 1\n\n    if image.dtype == bool and order != 0:\n        warn(\"Input image dtype is bool. Interpolation is not defined \"\n             \"with bool data type. Please set order to 0 or explicitely \"\n             \"cast input image to another data type. Starting from version \"\n             \"0.19 a ValueError will be raised instead of this warning.\",\n             FutureWarning, stacklevel=2)\n\n    perp_lines = _line_profile_coordinates(src, dst, linewidth=linewidth)\n    if image.ndim == 3:\n        pixels = [ndi.map_coordinates(image[..., i], perp_lines,\n                                      prefilter=order > 1,\n                                      order=order, mode=mode,\n                                      cval=cval) for i in\n                  range(image.shape[2])]\n        pixels = np.transpose(np.asarray(pixels), (1, 2, 0))\n    else:\n        pixels = ndi.map_coordinates(image, perp_lines, prefilter=order > 1,\n                                     order=order, mode=mode, cval=cval)\n    # The outputted array with reduce_func=None gives an array where the\n    # row values (axis=1) are flipped. Here, we make this consistent.\n    pixels = np.flip(pixels, axis=1)\n\n    if reduce_func is None:\n        intensities = pixels\n    else:\n        try:\n            intensities = reduce_func(pixels, axis=1)\n        except TypeError:  # function doesn't allow axis kwarg\n            intensities = np.apply_along_axis(reduce_func, arr=pixels, axis=1)\n\n    return intensities\n\n\ndef _line_profile_coordinates(src, dst, linewidth=1):\n    \"\"\"Return the coordinates of the profile of an image along a scan line.\n\n    Parameters\n    ----------\n    src : 2-tuple of numeric scalar (float or int)\n        The start point of the scan line.\n    dst : 2-tuple of numeric scalar (float or int)\n        The end point of the scan line.\n    linewidth : int, optional\n        Width of the scan, perpendicular to the line\n\n    Returns\n    -------\n    coords : array, shape (2, N, C), float\n        The coordinates of the profile along the scan line. The length of the\n        profile is the ceil of the computed length of the scan line.\n\n    Notes\n    -----\n    This is a utility method meant to be used internally by skimage functions.\n    The destination point is included in the profile, in contrast to\n    standard numpy indexing.\n    \"\"\"\n    src_row, src_col = src = np.asarray(src, dtype=float)\n    dst_row, dst_col = dst = np.asarray(dst, dtype=float)\n    d_row, d_col = dst - src\n    theta = np.arctan2(d_row, d_col)\n\n    length = int(np.ceil(np.hypot(d_row, d_col) + 1))\n    # we add one above because we include the last point in the profile\n    # (in contrast to standard numpy indexing)\n    line_col = np.linspace(src_col, dst_col, length)\n    line_row = np.linspace(src_row, dst_row, length)\n\n    # we subtract 1 from linewidth to change from pixel-counting\n    # (make this line 3 pixels wide) to point distances (the\n    # distance between pixel centers)\n    col_width = (linewidth - 1) * np.sin(-theta) / 2\n    row_width = (linewidth - 1) * np.cos(theta) / 2\n    perp_rows = np.array([np.linspace(row_i - row_width, row_i + row_width,\n                                      linewidth) for row_i in line_row])\n    perp_cols = np.array([np.linspace(col_i - col_width, col_i + col_width,\n                                      linewidth) for col_i in line_col])\n    return np.array([perp_rows, perp_cols])\n", "path": "skimage/measure/profile.py"}], "after_files": [{"content": "from warnings import warn\nimport numpy as np\nfrom scipy import ndimage as ndi\n\n\ndef profile_line(image, src, dst, linewidth=1,\n                 order=None, mode=None, cval=0.0,\n                 *, reduce_func=np.mean):\n    \"\"\"Return the intensity profile of an image measured along a scan line.\n\n    Parameters\n    ----------\n    image : ndarray, shape (M, N[, C])\n        The image, either grayscale (2D array) or multichannel\n        (3D array, where the final axis contains the channel\n        information).\n    src : array_like, shape (2, )\n        The coordinates of the start point of the scan line.\n    dst : array_like, shape (2, )\n        The coordinates of the end point of the scan\n        line. The destination point is *included* in the profile, in\n        contrast to standard numpy indexing.\n    linewidth : int, optional\n        Width of the scan, perpendicular to the line\n    order : int in {0, 1, 2, 3, 4, 5}, optional\n        The order of the spline interpolation, default is 0 if\n        image.dtype is bool and 1 otherwise. The order has to be in\n        the range 0-5. See `skimage.transform.warp` for detail.\n    mode : {'constant', 'nearest', 'reflect', 'mirror', 'wrap'}, optional\n        How to compute any values falling outside of the image.\n    cval : float, optional\n        If `mode` is 'constant', what constant value to use outside the image.\n    reduce_func : callable, optional\n        Function used to calculate the aggregation of pixel values\n        perpendicular to the profile_line direction when `linewidth` > 1.\n        If set to None the unreduced array will be returned.\n\n    Returns\n    -------\n    return_value : array\n        The intensity profile along the scan line. The length of the profile\n        is the ceil of the computed length of the scan line.\n\n    Examples\n    --------\n    >>> x = np.array([[1, 1, 1, 2, 2, 2]])\n    >>> img = np.vstack([np.zeros_like(x), x, x, x, np.zeros_like(x)])\n    >>> img\n    array([[0, 0, 0, 0, 0, 0],\n           [1, 1, 1, 2, 2, 2],\n           [1, 1, 1, 2, 2, 2],\n           [1, 1, 1, 2, 2, 2],\n           [0, 0, 0, 0, 0, 0]])\n    >>> profile_line(img, (2, 1), (2, 4))\n    array([1., 1., 2., 2.])\n    >>> profile_line(img, (1, 0), (1, 6), cval=4)\n    array([1., 1., 1., 2., 2., 2., 4.])\n\n    The destination point is included in the profile, in contrast to\n    standard numpy indexing.\n    For example:\n\n    >>> profile_line(img, (1, 0), (1, 6))  # The final point is out of bounds\n    array([1., 1., 1., 2., 2., 2., 0.])\n    >>> profile_line(img, (1, 0), (1, 5))  # This accesses the full first row\n    array([1., 1., 1., 2., 2., 2.])\n\n    For different reduce_func inputs:\n\n    >>> profile_line(img, (1, 0), (1, 3), linewidth=3, reduce_func=np.mean)\n    array([0.66666667, 0.66666667, 0.66666667, 1.33333333])\n    >>> profile_line(img, (1, 0), (1, 3), linewidth=3, reduce_func=np.max)\n    array([1, 1, 1, 2])\n    >>> profile_line(img, (1, 0), (1, 3), linewidth=3, reduce_func=np.sum)\n    array([2, 2, 2, 4])\n\n    The unreduced array will be returned when `reduce_func` is None or when\n    `reduce_func` acts on each pixel value individually.\n\n    >>> profile_line(img, (1, 2), (4, 2), linewidth=3, order=0,\n    ...     reduce_func=None)\n    array([[1, 1, 2],\n           [1, 1, 2],\n           [1, 1, 2],\n           [0, 0, 0]])\n    >>> profile_line(img, (1, 0), (1, 3), linewidth=3, reduce_func=np.sqrt)\n    array([[1.        , 1.        , 0.        ],\n           [1.        , 1.        , 0.        ],\n           [1.        , 1.        , 0.        ],\n           [1.41421356, 1.41421356, 0.        ]])\n    \"\"\"\n    if order is None:\n        order = 0 if image.dtype == bool else 1\n\n    if image.dtype == bool and order != 0:\n        warn(\"Input image dtype is bool. Interpolation is not defined \"\n             \"with bool data type. Please set order to 0 or explicitely \"\n             \"cast input image to another data type. Starting from version \"\n             \"0.19 a ValueError will be raised instead of this warning.\",\n             FutureWarning, stacklevel=2)\n    if mode is None:\n        warn(\"Default out of bounds interpolation mode 'constant' is \"\n             \"deprecated. In version 0.19 it will be set to 'reflect'. \"\n             \"To avoid this warning, set `mode=` explicitly.\",\n             FutureWarning, stacklevel=2)\n        mode = 'constant'\n\n    perp_lines = _line_profile_coordinates(src, dst, linewidth=linewidth)\n    if image.ndim == 3:\n        pixels = [ndi.map_coordinates(image[..., i], perp_lines,\n                                      prefilter=order > 1,\n                                      order=order, mode=mode,\n                                      cval=cval) for i in\n                  range(image.shape[2])]\n        pixels = np.transpose(np.asarray(pixels), (1, 2, 0))\n    else:\n        pixels = ndi.map_coordinates(image, perp_lines, prefilter=order > 1,\n                                     order=order, mode=mode, cval=cval)\n    # The outputted array with reduce_func=None gives an array where the\n    # row values (axis=1) are flipped. Here, we make this consistent.\n    pixels = np.flip(pixels, axis=1)\n\n    if reduce_func is None:\n        intensities = pixels\n    else:\n        try:\n            intensities = reduce_func(pixels, axis=1)\n        except TypeError:  # function doesn't allow axis kwarg\n            intensities = np.apply_along_axis(reduce_func, arr=pixels, axis=1)\n\n    return intensities\n\n\ndef _line_profile_coordinates(src, dst, linewidth=1):\n    \"\"\"Return the coordinates of the profile of an image along a scan line.\n\n    Parameters\n    ----------\n    src : 2-tuple of numeric scalar (float or int)\n        The start point of the scan line.\n    dst : 2-tuple of numeric scalar (float or int)\n        The end point of the scan line.\n    linewidth : int, optional\n        Width of the scan, perpendicular to the line\n\n    Returns\n    -------\n    coords : array, shape (2, N, C), float\n        The coordinates of the profile along the scan line. The length of the\n        profile is the ceil of the computed length of the scan line.\n\n    Notes\n    -----\n    This is a utility method meant to be used internally by skimage functions.\n    The destination point is included in the profile, in contrast to\n    standard numpy indexing.\n    \"\"\"\n    src_row, src_col = src = np.asarray(src, dtype=float)\n    dst_row, dst_col = dst = np.asarray(dst, dtype=float)\n    d_row, d_col = dst - src\n    theta = np.arctan2(d_row, d_col)\n\n    length = int(np.ceil(np.hypot(d_row, d_col) + 1))\n    # we add one above because we include the last point in the profile\n    # (in contrast to standard numpy indexing)\n    line_col = np.linspace(src_col, dst_col, length)\n    line_row = np.linspace(src_row, dst_row, length)\n\n    # we subtract 1 from linewidth to change from pixel-counting\n    # (make this line 3 pixels wide) to point distances (the\n    # distance between pixel centers)\n    col_width = (linewidth - 1) * np.sin(-theta) / 2\n    row_width = (linewidth - 1) * np.cos(theta) / 2\n    perp_rows = np.array([np.linspace(row_i - row_width, row_i + row_width,\n                                      linewidth) for row_i in line_row])\n    perp_cols = np.array([np.linspace(col_i - col_width, col_i + col_width,\n                                      linewidth) for col_i in line_col])\n    return np.array([perp_rows, perp_cols])\n", "path": "skimage/measure/profile.py"}]}