def calculate_solar_rotate_shift(mc, layer_index=0, **kwargs): """ Calculate the shift that must be applied to each layer of a mapcube in order to compensate for solar rotation. The center of the map is used to calculate the position of each mapcube layer. Shifts are calculated relative to a specified layer in the mapcube. When using this functionality, it is a good idea to check that the shifts that were applied to were reasonable and expected. One way of checking this is to animate the original mapcube, animate the derotated mapcube, and compare the differences you see to the calculated shifts. An example use is as follows. If you select data from the SDO cutout service, it is common to not use the solar tracking implemented by this service. This is because (at time of writing) the solar tracking implemented by that service moves the image by single pixels at a time. This is not optimal for many use cases, as it introduces artificial jumps in the data. So with solar tracking not chosen, the selected area is like a window through which you can see the Sun rotating underneath. mc : `sunpy.map.MapCube` The input mapcube. layer_index : int The index layer. Shifts are calculated relative to the time of this layer. ``**kwargs`` These keywords are passed to the function `sunpy.physics.transforms.differential_rotation.rot_hpc`. Returns ------- x, y : `~astropy.units.Quantity`, ~astropy.units.Quantity` The shifts relative to the index layer that can be applied to the input mapcube in order to compensate for solar rotation. The shifts are given in helioprojective co-ordinates. """ # Size of the data nt = len(mc.maps) # Storage for the shifts in arcseconds xshift_arcseconds = np.zeros((nt)) * u.arcsec yshift_arcseconds = np.zeros_like(xshift_arcseconds) # Calculate the rotations and the shifts for i, m in enumerate(mc): # Calculate the rotation of the center of the map 'm' at its # observation time to the observation time of the reference layer # indicated by "layer_index". newx, newy = rot_hpc(m.center.x, m.center.y, m.date, mc.maps[layer_index].date, **kwargs) # Calculate the shift in arcseconds xshift_arcseconds[i] = newx - mc.maps[layer_index].center.x yshift_arcseconds[i] = newy - mc.maps[layer_index].center.y return {"x": xshift_arcseconds, "y": yshift_arcseconds}
def test_rot_hpc(): # testing along the Sun-Earth line, observer is on the Earth x, y = rot_hpc(451.4 * u.arcsec, -108.9 * u.arcsec, '2012-06-15', '2012-06-15 16:05:23') np.testing.assert_almost_equal(x.to(u.arcsec).value, 574.2, decimal=1) np.testing.assert_almost_equal(y.to(u.arcsec).value, -108.4, decimal=1) # Test that astropy Angles are returned and that they have the expected # units isinstance(x, Angle) x.unit == u.arcsec isinstance(y, Angle) y.unit == u.arcsec