Repository: sunpy/sunpy

Issue:
Confusing section in Differential rotation example
Part of the differential rotating a map example says

> For the reprojection, the definition of the target frame can be counter-intuitive. We will be transforming from the original frame to the RotatedSunFrame version of the output frame with rotated_time set to the time of the original frame.

I agree this is counter-intuitive, but there is no description given as to **why** `in_time` has to be supplied to `RotatedSunFrame`, as opposed to `out_time`. I think the example would be improved with an explanation/justification of this counter-intuitive part.


Discussion:
I'm going to go into gory detail here, but it can't/shouldn't all go into the gallery example.

Let `input` be the coordinate frame of the source map, at the time `input.obstime`.
Let `output` be the desired coordinate frame of the destination map, at the time `output.obstime`.

The desire is to reproject the map from `input` to `output` with the accounting of differential rotation from `input.obstime` to `output.obstime`.  You have to use `RotatedSunFrame` *somewhere* because `reproject` has no concept of coordinates moving in inertial space.  The question is the proper use of that metaframe.

One's intuition might be that the destination frame should be something like `RotatedSunFrame(..., rotated_time=output.obstime)`, for some choice of base frame.  However, there are two ways to see that this is incorrect:

1. You'd be asking `reproject` to transform from inertial locations at `input.obstime` to inertial locations at `output.obstime`, and thus you haven't addressed the core problem that `reproject` can't do that.
2. You can simply ponder the two possible choices for base frame:
    - `RotatedSunFrame(input, rotated_time=output.obstime)` doesn't make sense because the destination frame doesn't actually make use of `output` aside from its time.  Admittedly, `input` and `output` would frequently be the same coordinate system, but even if they are both `Helioprojective`, they are likely to have different observers.  You have to use `output` somewhere!
    - `RotatedSunFrame(output, rotated_time=output.obstime)` doesn't make sense because it essentially does nothing: you're trying to differentially rotate the coordinate frame to its own time.

Instead, the proper destination frame is `RotatedSunFrame(output, ...)`, and the remaining question is the specification of `rotated_time`.  There are two ways to see that the correct answer is `rotated_time=input.obstime`:

1. Both `input` and `RotatedSunFrame(output, rotated_time=input.obstime)` point to inertial locations at the time `input.obstime`.  Thus, you have addressed the core problem with use `reproject`: you are no longer reprojecting across time.
2. `RotatedSunFrame(output, rotated_time=output.obstime)` doesn't do anything: see earlier.

----

In principle, it would also be valid to reproject from `RotatedSunFrame(input, rotated_time=output.obstime)` to `output`.  However, if the user is using `reproject` in the way of the gallery example, the source frame can't be a `RotatedSun*` frame.
> Both `input` and `RotatedSunFrame(output, rotated_time=input.obstime)` point to inertial locations at the time `input.obstime`.

For the gallery example, I think a slightly wordier version of this sentence may be sufficient.
@ayshih Not sure if this is accurate but I tried to put two and two together from your explanation, the example, and the documentation. Does it work?

> For the reprojection, the definition of the target frame can be counter-intuitive. We will be transforming from the original frame to the `RotatedSunFrame` version of the output frame with `rotated_time` set to the time of the original frame.
> 
> We use `input.obstime` instead of `output.obstime` here because of the way `RotatedSunFrame` works. The `RotatedSunFrame` class allows one to specify coordinates in a coordinate frame prior to an amount of solar (differential) rotation being applied. That is, the coordinate will point to a location in inertial space at some time (here, `input.obstime`), but will use a coordinate system at a different time (here, `out_frame`) to refer to that point, while accounting for the differential rotation between those two times.
> 
> Here, we're differentially rotating the `out_frame` to the `input.obstime` because we want the new `RotatedSunFrame` and the `in_frame` to point to inertial locations at the same time.
@chouhanaryan Your description is pretty good, but I suggest rewriting it so:

> For the reprojection, the definition of the target frame can be counter-intuitive.
> Reprojection should be performed between two frames that point to inertial locations at the same time, but `out_frame` is not at the same time as the original frame (`out_time` versus `in_time`).
> The `RotatedSunFrame` metaframe allows one to specify coordinates in a coordinate frame at one time (here, `out_frame`) to refer to inertial locations at a different time (here, `in_time`, which is supplied through the keyword argument `rotated_time`).
> `RotatedSunFrame` will account for the appropriate amount of solar (differential) rotation for the time difference between `out_time` and `in_time`.

Resolving patch:
diff --git a/examples/differential_rotation/reprojected_map.py b/examples/differential_rotation/reprojected_map.py
--- a/examples/differential_rotation/reprojected_map.py
+++ b/examples/differential_rotation/reprojected_map.py
@@ -41,9 +41,16 @@
 
 ##############################################################################
 # For the reprojection, the definition of the target frame can be
-# counter-intuitive.  We will be transforming from the original frame to the
-# `~sunpy.coordinates.metaframes.RotatedSunFrame` version of the output frame
-# with ``rotated_time`` set to the time of the original frame.
+# counter-intuitive. Reprojection should be performed between two frames that
+# point to inertial locations at the same time, but ``out_frame`` is not at
+# the same time as the original frame (``out_time`` versus ``in_time``).
+# The `~sunpy.coordinates.metaframes.RotatedSunFrame` metaframe allows one to
+# specify coordinates in a coordinate frame at one time (here, ``out_frame``)
+# to refer to inertial locations at a different time (here, ``in_time``,
+# which is supplied through the keyword argument ``rotated_time``).
+# `~sunpy.coordinates.metaframes.RotatedSunFrame` will account for the
+# appropriate amount of solar (differential) rotation for the time
+# difference between ``out_time`` and ``in_time``.
 
 rot_frame = RotatedSunFrame(base=out_frame, rotated_time=in_time)
 print(rot_frame)


Test patch: