def eoa(self, *args, array=True): """Takes in coordinates and returns the area of pixels on sun. Each pixel is projected onto the sun, and therefore pixels close to the limbs have vastly greater areas. This function uses a closed form solution to a spherical area integral to calulate the area based on the heliographic coordinate unit vectors of each corner of the pixel. We use these to calculate a solid angle of a pyramid with its apex at the center of the sun. """ print ("Calculating element of area.") # Assume coordinate is in center of pixel. # Information on pixel standard is in this article. # http://www.aanda.org/component/article?access=bibcode&bibcode=&bibcode=2002A%2526A...395.1061GFUL if array: lon, lat = self.heliographic(corners=True) lon = lon*np.pi/180 lat = lat*np.pi/180 # Calculating unit vectors of pixel corners for solid angle. r1 = self._spherical_to_cartesian(lon, lat, 0, 0) r2 = self._spherical_to_cartesian(lon, lat, 1, 0) r3 = self._spherical_to_cartesian(lon, lat, 1, 1) r4 = self._spherical_to_cartesian(lon, lat, 0, 1) else: x = args[0] y = args[1] lonUL, latUL = self.heliographic(x - .5, y - .5) lonLL, latLL = self.heliographic(x + .5, y - .5) lonLR, latLR = self.heliographic(x + .5, y + .5) lonUR, latUR = self.heliographic(x - .5, y + .5) # Calculating unit vectors of pixel corners for solid angle. r1 = np.array([np.cos(np.deg2rad(latUL))*np.cos(np.deg2rad(lonUL)), np.cos(np.deg2rad(latUL))*np.sin(np.deg2rad(lonUL)), np.sin(np.deg2rad(latUL))]) r2 = np.array([np.cos(np.deg2rad(latLL))*np.cos(np.deg2rad(lonLL)), np.cos(np.deg2rad(latLL))*np.sin(np.deg2rad(lonLL)), np.sin(np.deg2rad(latLL))]) r3 = np.array([np.cos(np.deg2rad(latLR))*np.cos(np.deg2rad(lonLR)), np.cos(np.deg2rad(latLR))*np.sin(np.deg2rad(lonLR)), np.sin(np.deg2rad(latLR))]) r4 = np.array([np.cos(np.deg2rad(latUR))*np.cos(np.deg2rad(lonUR)), np.cos(np.deg2rad(latUR))*np.sin(np.deg2rad(lonUR)), np.sin(np.deg2rad(latUR))]) # Calculate solid angle of pixel based on a pyrimid shaped polygon. # See http://planetmath.org/solidangleofrectangularpyramid cross1 = M.cross(r1, r2, axis=0) cross2 = M.cross(r3, r4, axis=0) numerator1 = M.dot(cross1, r3) numerator2 = M.dot(cross2, r1) solid_angle1 = 2*M.arctan2(numerator1, (M.dot(r1, r2) + M.dot(r2, r3) + M.dot(r3, r1) + 1)) solid_angle2 = 2*M.arctan2(numerator2, (M.dot(r3, r4) + M.dot(r4, r1) + M.dot(r3, r1) + 1)) solid_angle = solid_angle1 + solid_angle2 r = self.RSUN_METERS*100 # Convert to centimeters if array: self.area = abs((r**2)*solid_angle) ind = np.where(self.Rg[1:len(self.Rg)-1, 1:len(self.Rg)-1] > self.rsun) del self.Rg self.area[ind] = np.nan return else: if self.rg > self.rsun: return np.nan else: return np.abs((r**2)*solid_angle)