def _delta_solar_skyfield(ra_x, dec_y, met, **kwargs): """ Function to compute the offsets from the center of the Sun as a function of time. Use the tStep argument to define how often you want to update the solar ephemeris. Default is every 5 seconds. Inputs: ra_x, dec_y, and met are all arrays that contain the RA, Dec, and time of arrival of each count, respectively. The arrival time must have astropy units attached to it. Outputs: sun_x, sun_y are the x and y values (in arcseconds) from the center of the Sun in the +North and +West directions. """ import astropy.units as u from nustar_pysolar.utils import skyfield_ephem # Don't think this is needed # from sunpy import sun # Deprecated from sunpy v1 onwards # from sunpy.coordinates import get_sun_P # Use new version instead from sunpy.coordinates import sun # How often you want to update the solar ephemeris: tStep = kwargs.get('tStep', 5.0) tStep = tStep * u.s load_path = kwargs.get('load_path', None) observer, TheSun, ts = skyfield_ephem(load_path=load_path, parallax_correction=True, utc=met[0]) # How many events do you want to do? maxEvt = kwargs.get('maxEvt', len(ra_x)) # Keep last time we updated things last_met = met[0] - tStep * 2. last_i = 0 sun_x = np.zeros_like(ra_x) sun_y = np.zeros_like(dec_y) for i in np.arange(len(ra_x)): if ((met[i] - last_met) > tStep): last_met = met[i] tcheck = ts.from_astropy(last_met) astrometric = observer.at(tcheck).observe(TheSun) this_ra, this_dec, dist = astrometric.radec() # Get the center of the Sun, and assign it degrees. # Doing it this was is necessary to do the vector math below. sun_pos = np.array( [this_ra.to(u.deg).value, this_dec.to(u.deg).value]) * u.deg # sun_np = get_sun_P(last_met) sun_np = sun.P(last_met) # Rotation matrix for a counter-clockwise rotation since we're going # back to celestial north from solar north rotMatrix = np.array([[np.cos(sun_np), np.sin(sun_np)], [-np.sin(sun_np), np.cos(sun_np)]]) # Diagnostics # di = (i -last_i) # print("Updating Sun position...") # if di > 0: # print(i, di) # dt = toc() # tic() # last_i = i # print("Time per event: ",dt / float(di) ) # From here on we do things for every photon: ph_pos = np.array([ra_x[i].value, dec_y[i].value]) * u.deg offset = ph_pos - sun_pos # Project the offset onto the Sun delta_offset = ((np.dot(offset, rotMatrix)).to(u.arcsec)) # Account for East->West conversion for +X direction in heliophysics coords delta_offset = delta_offset * [-1., 1.] sun_x[i] = delta_offset[0] sun_y[i] = delta_offset[1] if (i > maxEvt): break return sun_x, sun_y
def get_skyfield_position(time, offset, load_path=None, parallax_correction=False): """Code for converting solar coordinates to astrometric (J200) RA/Dec coordinates. Parameters ---------- time: Date that is parsable by sunpy.time.parse_time() i.e., time='2016-07-26T19:53:15.00' offset: Offset from the center of the Sun. Must have units from astropy: i.e.: offset = np.array([1000, 150]) * u.arcsec load_path (optional): Relative path from currently location to store bsp files parallax_correction: Use the NuSTAR TLE to correct for orbital parallax Returns ---------- sky_position: Two-element array giving the [RA, Dec] coordinates of the target location. Note this is given in astrometric (J2000) RA/Dec, which is what we need for the NuSTAR planning system. Notes ---------- Syntax: skyfield_position = get_skyfield_position(time, offset) """ from astropy.time import Time # Replaced with newer sunpy v1 function # from sunpy import sun from sunpy.coordinates import sun from nustar_pysolar.utils import skyfield_ephem start_date = parse_time(time) utc = Time(start_date) observer, sunephem, ts = skyfield_ephem( load_path=load_path, parallax_correction=parallax_correction, utc=utc) tcheck = ts.from_astropy(utc) geocentric = observer.at(tcheck).observe(sunephem) this_ra_geo, this_dec_geo, dist = geocentric.radec() # Get the solar north pole angle. cgs --> radians # sun_np = sunpy.sun.solar_north(t=time).cgs # Update for sunpy v1.0+ sun_np = sun.P(time).cgs # Get the center of the Sun, and assign it degrees. # Doing it this was is necessary to do the vector math below. sun_pos = np.array( [this_ra_geo.to(u.deg).value, this_dec_geo.to(u.deg).value]) * u.deg # Rotation matrix for a counter-clockwise rotation since we're going # back to celestial north from solar north rotMatrix = np.array([[np.cos(sun_np), np.sin(sun_np)], [-np.sin(sun_np), np.cos(sun_np)]]) # Project the offset onto the Sun delta_offset = np.dot(offset, rotMatrix) # Scale to RA based on the declination. delta_offset = delta_offset * np.array([1. / np.cos(sun_pos[1]), 1.]) # Account for the fact that +Ra == East and we have defined +X = West delta_offset = delta_offset * [-1.0, 1.0] # Apply the offset and return the sky position. sky_position = sun_pos + delta_offset return sky_position
def get_skyfield_position(time, offset, load_path=None, parallax_correction=False): """Code for converting solar coordinates to astrometric (J200) RA/Dec coordinates. Parameters ---------- time: Date that is parsable by sunpy.time.parse_time() i.e., time='2016-07-26T19:53:15.00' offset: Offset from the center of the Sun. Must have units from astropy: i.e.: offset = np.array([1000, 150]) * u.arcsec load_path (optional): Relative path from currently location to store bsp files parallax_correction: Use the NuSTAR TLE to correct for orbital parallax Returns ---------- sky_position: Two-element array giving the [RA, Dec] coordinates of the target location. Note this is given in astrometric (J2000) RA/Dec, which is what we need for the NuSTAR planning system. Notes ---------- Syntax: skyfield_position = get_skyfield_position(time, offset) """ from astropy.time import Time import sunpy.sun from nustar_pysolar.utils import skyfield_ephem start_date = parse_time(time) utc = Time(start_date) observer, sun, ts = skyfield_ephem(load_path=load_path, parallax_correction=parallax_correction, utc=utc) tcheck = ts.from_astropy(utc) geocentric = observer.at(tcheck).observe(sun) this_ra_geo, this_dec_geo, dist = geocentric.radec() # Get the solar north pole angle. cgs --> radians sun_np = sunpy.sun.solar_north(t=time).cgs # Get the center of the Sun, and assign it degrees. # Doing it this was is necessary to do the vector math below. sun_pos = np.array([this_ra_geo.to(u.deg).value, this_dec_geo.to(u.deg).value])*u.deg # Rotation matrix for a counter-clockwise rotation since we're going # back to celestial north from solar north rotMatrix = np.array([[np.cos(sun_np), np.sin(sun_np)], [-np.sin(sun_np), np.cos(sun_np)]]) # Project the offset onto the Sun delta_offset = np.dot(offset, rotMatrix) # Scale to RA based on the declination. delta_offset = delta_offset * np.array([1. / np.cos(sun_pos[1]), 1.]) # Account for the fact that +Ra == East and we have defined +X = West delta_offset = delta_offset * [-1.0, 1.0] # Apply the offset and return the sky position. sky_position = sun_pos + delta_offset return sky_position