Coordinate Transformations
SDO/HMI Data Products are returned in Helioprojective Cartesian pixel coordinates. In order to calculate the spacecraft and solar rotation velocity corrections, we need to convert this to the Heliographic Carrington Coordinate System (sun centered coordinate system). In addition to being sun-centered, Heliographic Carrington coordinates also rotate with respect to the Carrington rotation period. Transformations are based off Thompson (2006).
Coordinate functions are here.
Pixel Array Computation
The first step in the coordinate transformation is computation of the pixel-wise coordinate arrays with respect to solar center. We do this by taking into account the reference pixels from the header file.
We then calculate the array of \mu and radius values for that image, where \mu = cos(\theta). First, we determine pixel size in physical coordinates (solar radii) and then calculate the center-to-limb angles. We get the radius by determining the distance in solar radii to each pixel.
def coordinates(smap):
"""
calculate array of mu values and cartesian
coordinates for image
Parameters
----------
smap: Sunpy map object
Returns
-------
x: array of x coordinates in helioprojective cartesian system
y: array of y coordinates in helioprojective cartesian system
pd: array of pixel distances
r: array of solar radius values
d: observer distance from sun in solar radii
mu: array of mu values
"""
# distance of observer to sun in solar radii
d = smap.fits_header['DSUN_OBS'] / smap.fits_header['RSUN_REF']
# focal length in pixels
f = 180. * 3600. / np.pi / smap.fits_header['CDELT1']
# get cartesian x, y map scales
x, y = get_map_scales(smap)
# distance (in pixels) to pixel
pd = np.sqrt(x ** 2 + y ** 2)
# distance (in solar r) to pixel
pr = f * f * pd * pd + pd ** 4 - d * d * pd ** 4 + 0.J
r = (d * f * pd - np.sqrt(pr)) / (f * f + pd * pd)
# separate complex parts
r = r.real
# get mu array
pr = 1 - r ** 2 + 0.J
cos_alpha = (np.sqrt(pr)).real
sin_alpha = r.real
cos_theta = ((d - np.sqrt(pr)) / np.sqrt(r ** 2 + (d - np.sqrt(pr)) ** 2)).real
sin_theta = (np.sqrt(1 - cos_theta ** 2)).real
mu = cos_alpha * cos_theta - sin_alpha * sin_theta
return x, y, pd, r, d, mu
Coordinate Transform
We are able to apply the coordinate transformation based on a calculated rotation matrix. We get an array of coordinates in the westward, northward, and radial direction.
def vel_coords(x, y, pd, r, smap):
"""
calculate coordinate transformation to heliographic Carrington coordinates
Parameters
----------
x: array of x coordinates in helioprojective cartesian system
y: array of y coordinates in helioprojective cartesian system
pd: array of pixel distances
r: array of solar radius values
smap: Sunpy map object
Returns
-------
wij: array of pixel coordinates relative to solar center in westward direction
nij: array of pixel coordinates relative to solar center in northward direction
rij: array of pixel coordinates relative to solar center in radial direction
"""
head = smap.fits_header
crota2 = head['CROTA2'] # deg
# transform each pixel to get into Heliographic CR Coordinates
dw = y * np.sin(np.deg2rad(crota2)) + x * np.cos(np.deg2rad(crota2))
dn = y * np.cos(np.deg2rad(crota2)) - x * np.sin(np.deg2rad(crota2))
# get cartesian coordinates for velocity calculations
pr = 1 - r ** 2 + 0.J
wij = r * dw / pd
nij = r * dn / pd
rij = (np.sqrt(pr)).real
return wij, nij, rij
Fix Mu Values
Lastly, we remove all pixels with mu values less than 0.1 because our limb-brightening model does poorly in correcting near the edge of the Solar disk.
def fix_mu(mu, smaps, mu_cutoff=0.3):
"""
function to remove pixel values where mu is less than 0.1
Parameters
----------
mu: cosine of the center to limb angle
smaps: list of Sunpy map object
mu_cutoff: minimum mu cutoff value
Returns
-------
mu: corrected cosine of the center to limb angle
smap: corrected Sunpy map object
"""
# remove pixel values where mu < mu_cut (0.3)
bad_inds = np.where(mu <= mu_cutoff)
# fix arrays
for smap in smaps:
smap.data[bad_inds] = 0
return smaps