Repository: sunpy/sunpy

Issue:
Explain why `extract_along_coords` returns coordinates
### Describe the feature

[`extract_along_coord`](https://docs.sunpy.org/en/stable/generated/api/sunpy.map.extract_along_coord.html#sunpy.map.extract_along_coord) takes coordinates to get the value of a map at, but also returns a set of coordinates. I presume these are not the same coordinates, but the docstring does not explain what they are or why they're useful. This is a request to add input and output parameter documentation to the docstring of `extract_along_coord`.

### Proposed solution

_No response_


Discussion:
The returned coordinates are the coordinates for the pixels from which the values were taken, as the function walks the pixels. Also it returns the same number of coordinates as values, so you can plot them or whatever you want.
Had a play around, and I think putting a version of this in the docstring would help:

![extract_along_coord](https://user-images.githubusercontent.com/6197628/222276584-a195b528-96e5-43df-986e-f0d2697e9095.png)


```python
import matplotlib.pyplot as plt

import astropy.units as u
from astropy.coordinates import SkyCoord

import sunpy.map
from sunpy.data.sample import AIA_171_IMAGE

m = sunpy.map.Map(AIA_171_IMAGE)

coords = SkyCoord(
    Tx=[715, 720, 731] * u.arcsec,
    Ty=[-360, -350, -347] * u.arcsec,
    frame=m.coordinate_frame,
)

intens, intens_coords = sunpy.map.extract_along_coord(m, coords)

fig = plt.figure()
ax = fig.add_subplot(111, projection=m)
m.plot(ax)
ax.plot_coord(coords, marker='o', color='black', label="Input coords")
ax.plot_coord(intens_coords, marker='s', color='tab:purple', label="Sampled coords")
ax.set_ylim(360, 360 + 10)
ax.set_xlim(807, 807 + 10)
ax.legend()
plt.show()
```
🤔 also the picture above is now making me suspicious about how `extract_along_coord` works, there are clearly some pixels the black line goes through that aren't sampled in the output...
Some pixels will always be "skipped", ~but it appears that the implementation of Bresenham's line algorithm is slightly bugged, because it's not picking the correct pixels.~

Edit: Not a bug, see https://github.com/sunpy/sunpy/pull/6817#issuecomment-1451943040
~See #6817 for the bug fix.~ (Edit: not a bug)  The correct result is:
![Figure_1](https://user-images.githubusercontent.com/991759/222304190-fec51d51-6f3b-4697-bc18-50da21108e94.png)
> 🤔 also the picture above is now making me suspicious about how `extract_along_coord` works, there are clearly some pixels the black line goes through that aren't sampled in the output...

Two notes (that should go into our documentation):
- Bresenham's line algorithm does not return every pixel that is touched by the line segment.  When a line segment passes through a pixel, but that pixel is not picked, that's because that pixel was not closer to the line than its neighbors.
- We effectively round each coordinate to the nearest pixel center before running Bresenham's line algorithm, which is intended for integers.  That means that the actually selected pixels can look sub-optimal depending on the offsets of coordinates from the pixel centers.  Here is the visualization if the coordinates are at pixel centers:
![Figure_1](https://user-images.githubusercontent.com/991759/222459779-872db3bf-5f1e-494c-9ac3-c817133306a3.png)


Resolving patch:
diff --git a/sunpy/map/maputils.py b/sunpy/map/maputils.py
--- a/sunpy/map/maputils.py
+++ b/sunpy/map/maputils.py
@@ -454,25 +454,34 @@ def _bresenham(*, x1, y1, x2, y2):
 
 def extract_along_coord(smap, coord):
     """
-    Return the value of the image array at every pixel the coordinate path intersects.
+    Extract pixel values from a map along a path that approximates a coordinate path.
 
-    For a given coordinate ``coord``, find all the pixels that cross the coordinate
-    and extract the values of the image array in ``smap`` at these points. This is done by applying
-    `Bresenham's line algorithm <http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm>`_
-    between the consecutive coordinates, in pixel space, and then indexing the data
-    array of ``smap`` at those points.
+    Each pair of consecutive coordinates in the provided coordinate array defines a
+    line segment in pixel space.  The approximate pixel path for each line segment is
+    determined by applying
+    `Bresenham's line algorithm <http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm>`_.
+    The resulting pixel path does not necessarily include every pixel that is
+    intersected by each line segment.
 
     Parameters
     ----------
     smap : `~sunpy.map.GenericMap`
         The sunpy map.
     coord : `~astropy.coordinates.SkyCoord`
-        Coordinate along which to extract intensity.
+        The coordinate array that defines the path for extraction.
 
     Returns
     -------
-    values : `~astropy.units.Quantity`
-    value_coords : `~astropy.coordinates.SkyCoord`
+    pixel_values : `~astropy.units.Quantity`
+         The pixel values along a path that approximates the coordinate path.
+    pixel_coords : `~astropy.coordinates.SkyCoord`
+         The coordinates for the pixels from which the values were extracted.
+
+    Notes
+    -----
+    The provided coordinates are first rounded to the nearest corresponding pixel,
+    which means that the coordinates used for calculations may be shifted relative
+    to the provided coordinates by up to half a pixel.
 
     Examples
     --------
@@ -498,7 +507,7 @@ def extract_along_coord(smap, coord):
         pix.append(b)
     pix = np.vstack(pix)
 
-    intensity = u.Quantity(smap.data[pix[:, 0], pix[:, 1]], smap.unit)
-    coord_new = smap.wcs.pixel_to_world(pix[:, 1], pix[:, 0])
+    pixel_values = u.Quantity(smap.data[pix[:, 0], pix[:, 1]], smap.unit)
+    pixel_coords = smap.wcs.pixel_to_world(pix[:, 1], pix[:, 0])
 
-    return intensity, coord_new
+    return pixel_values, pixel_coords


Test patch: