def test_hgs_hgc_sunspice(): # Compare our HGS->HGC transformation against SunSPICE # "HEQ" is another name for HEEQ, which is equivalent to Heliographic Stonyhurst # "Carrington" does not include light travel time to the observer or aberration due to observer # motion, while our HGC includes both effects. # # IDL> coord = [1.d, 0.d, 10.d] # IDL> convert_sunspice_lonlat, '2019-06-01', coord, 'HEQ', 'Carrington', /au, /degrees # IDL> print, coord # 1.0000000 16.688242 10.000000 old = SkyCoord(0 * u.deg, 10 * u.deg, 1 * u.AU, frame=HeliographicStonyhurst(obstime='2019-06-01')) new = old.heliographic_carrington # Calculate the difference in longitude due to light travel time from the Sun to the Earth delta_lon = (14.1844 * u.deg / u.day) * (sun.earth_distance(old.obstime) / speed_of_light) # Calculate the difference in longitude due to aberration due to Earth motion # This approximation should be replaced with a more accurate calcuation, but for now it simply # uses the same approximation as in our implementation. delta_lon -= 20.496 * u.arcsec * 1 * u.AU / sun.earth_distance(old.obstime) assert_quantity_allclose(new.lon, 16.688242 * u.deg + delta_lon, atol=1e-2 * u.arcsec, rtol=0) assert_quantity_allclose(new.lat, old.lat) assert_quantity_allclose(new.radius, old.radius)
def test_hgs_hgc_sunspice(): # Compare our HGS->HGC transformation against SunSPICE # "HEQ" is another name for HEEQ, which is equivalent to Heliographic Stonyhurst # "Carrington" does not include light travel time to the observer, which our HGC includes # # IDL> coord = [1.d, 0.d, 10.d] # IDL> convert_sunspice_lonlat, '2019-06-01', coord, 'HEQ', 'Carrington', /au, /degrees # IDL> print, coord # 1.0000000 16.688242 10.000000 old = SkyCoord(0 * u.deg, 10 * u.deg, 1 * u.AU, frame=HeliographicStonyhurst(obstime='2019-06-01')) new = old.transform_to(HeliographicCarrington(observer='earth')) # Calculate the difference in longitude due to light travel time from the Sun to the Earth delta_lon = sidereal_rotation_rate * (sun.earth_distance(old.obstime) - _RSUN) / speed_of_light assert_quantity_allclose(new.lon, 16.688242 * u.deg + delta_lon, atol=1e-2 * u.arcsec, rtol=0) assert_quantity_allclose(new.lat, old.lat) assert_quantity_allclose(new.radius, old.radius)
def _default_observer_coordinate(self): # Override missing metadata in the observer coordinate dsun_obs = self.meta.get('dsun_obs', sun.earth_distance(self.date).to_value(u.m)) return SkyCoord(self.meta.get('hgln_obs', 0.0) * u.deg, self.meta.get('hglt_obs', 0.0) * u.deg, self.meta.get('dsun_obs', dsun_obs) * u.m, frame="heliographic_stonyhurst")
def LOFAR_to_sun(smap): obs_coord = SkyCoord(smap.reference_coordinate, distance=sun.earth_distance(smap.date),obstime=smap.date) rot_ang = 0#sun.P(smap.date) smap_rot = smap.rotate(angle=rot_ang) smap_out_head = header_helper.make_fitswcs_header(smap_rot.data, obs_coord.transform_to(frames.Helioprojective), u.Quantity(smap_rot.reference_pixel), u.Quantity(smap_rot.scale)) smap_out_head['cdelt1'] = abs(smap_out_head['cdelt1']) #make sure axis increases properly (is this right?) smap_out = sunpy.map.Map(smap_rot.data, smap_out_head,plot_settings={'cmap':'viridis'}) smap_out.meta['wavelnth'] = smap.meta['crval3']/1e6 smap_out.meta['waveunit'] = "MHz" return smap_out
def test_earth_distance_array_time(): # Validate against published values from the Astronomical Almanac (2013) sunearth_distance = sun.earth_distance( Time(['2013-04-01', '2013-12-01'], scale='tt')) assert_quantity_allclose(sunearth_distance[0], 0.9992311 * u.AU, rtol=0, atol=5e-8 * u.AU) assert_quantity_allclose(sunearth_distance[1], 0.9861362 * u.AU, rtol=0, atol=5e-8 * u.AU)
def __init__(self, data, header, **kwargs): super().__init__(data, header, **kwargs) # Fill in some missing info self.meta['observatory'] = 'MLSO' self.meta['detector'] = 'KCor' self.meta['waveunit'] = 'nanometer' # Since KCor is on Earth, no need to raise the warning in mapbase self.meta['dsun_obs'] = (sun.earth_distance(self.date)).to(u.m).value self.meta['hgln_obs'] = 0.0 self._nickname = self.detector self.plot_settings['cmap'] = self._get_cmap_name() self.plot_settings['norm'] = ImageNormalize(stretch=source_stretch(self.meta, PowerStretch(0.25)), clip=False) # Negative value pixels can appear that lead to ugly looking images. # This can be fixed by setting the lower limit of the normalization. self.plot_settings['norm'].vmin = 0.0
def make_map(self): # still in beta version, use with caution # ref : https://gist.github.com/hayesla/42596c72ab686171fe516f9ab43300e2 hdu = fits.open(self.fname) header = hdu[0].header data = np.squeeze(hdu[0].data) data = np.squeeze(hdu[0].data) obstime = Time(header['date-obs']) frequency = header['crval3'] * u.Hz reference_coord = SkyCoord(header['crval1'] * u.deg, header['crval2'] * u.deg, frame='gcrs', obstime=obstime, distance=sun_coord.earth_distance(obstime), equinox='J2000') lofar_loc = EarthLocation(lat=52.905329712 * u.deg, lon=6.867996528 * u.deg) # location of the center of LOFAR lofar_coord = SkyCoord(lofar_loc.get_itrs(Time(obstime))) reference_coord_arcsec = reference_coord.transform_to( frames.Helioprojective(observer=lofar_coord)) cdelt1 = (np.abs(header['cdelt1']) * u.deg).to(u.arcsec) cdelt2 = (np.abs(header['cdelt2']) * u.deg).to(u.arcsec) P1 = sun_coord.P(obstime) new_header = sunpy.map.make_fitswcs_header( data, reference_coord_arcsec, reference_pixel=u.Quantity( [header['crpix1'] - 1, header['crpix2'] - 1] * u.pixel), scale=u.Quantity([cdelt1, cdelt2] * u.arcsec / u.pix), rotation_angle=-P1, wavelength=frequency.to(u.MHz), observatory='LOFAR') lofar_map = sunpy.map.Map(data, new_header) lofar_map_rotate = lofar_map.rotate() bl = SkyCoord(-2500 * u.arcsec, -2500 * u.arcsec, frame=lofar_map_rotate.coordinate_frame) tr = SkyCoord(2500 * u.arcsec, 2500 * u.arcsec, frame=lofar_map_rotate.coordinate_frame) lofar_submap = lofar_map_rotate.submap(bl, tr) return lofar_submap
0 * u.arcsec, obstime=obstime, observer="earth", frame=frames.Helioprojective) ###################################################################################### # Now we establish our location on the Earth, in this case let's consider a high altitude # balloon launched from Fort Sumner, NM. Fort_Sumner = EarthLocation(lat=34.4900 * u.deg, lon=-104.221800 * u.deg, height=40 * u.km) ###################################################################################### # Now lets convert this to a local measurement of Altitude and Azimuth. frame_altaz = AltAz(obstime=Time(obstime), location=Fort_Sumner) sun_altaz = c.transform_to(frame_altaz) print(f'Altitude is {sun_altaz.T.alt} and Azimuth is {sun_altaz.T.az}') ###################################################################################### # Next let's check this calculation by converting it back to helioprojective. # We should get our original input which was the center of the Sun. # To go from Altitude/Azimuth to Helioprojective, you will need the distance to the Sun. # solar distance. Define distance with SunPy's almanac. distance = sun.earth_distance(obstime) b = SkyCoord(az=sun_altaz.T.az, alt=sun_altaz.T.alt, distance=distance, frame=frame_altaz) sun_helio = b.transform_to(frames.Helioprojective(observer="earth")) print(f'The helioprojective point is {sun_helio.T.Tx}, {sun_helio.T.Ty}')
def test_earth_distance(): # Validate against a published value from Astronomical Algorithms (Meeus 1998, p.191) assert_quantity_allclose(sun.earth_distance('1992-Oct-13'), 0.997608 * u.AU, atol=5e-7 * u.AU)
def backprojection(calibrated_event_list, pixel_size: u.arcsec = (1., 1.) * u.arcsec, image_dim: u.pix = (64, 64) * u.pix): """ Given a stacked calibrated event list fits file create a back projection image. .. warning:: The image is not in the right orientation! Parameters ---------- calibrated_event_list : str filename of a RHESSI calibrated event list pixel_size : `~astropy.units.Quantity` instance the size of the pixels in arcseconds. Default is (1,1). image_dim : `~astropy.units.Quantity` instance the size of the output image in number of pixels Returns ------- out : RHESSImap Return a backprojection map. Examples -------- This example is broken. >>> import sunpy.data >>> import sunpy.data.sample # doctest: +REMOTE_DATA >>> import sunpy.instr.rhessi as rhessi >>> map = rhessi.backprojection(sunpy.data.sample.RHESSI_EVENT_LIST) # doctest: +SKIP >>> map.peek() # doctest: +SKIP """ # import sunpy.map in here so that net and timeseries don't end up importing map import sunpy.map pixel_size = pixel_size.to(u.arcsec) image_dim = np.array(image_dim.to(u.pix).value, dtype=int) afits = sunpy.io.read_file(calibrated_event_list) info_parameters = afits[2] xyoffset = info_parameters.data.field('USED_XYOFFSET')[0] time_range = TimeRange( info_parameters.data.field('ABSOLUTE_TIME_RANGE')[0], format='utime') image = np.zeros(image_dim) # find out what detectors were used det_index_mask = afits[1].data.field('det_index_mask')[0] detector_list = (np.arange(9) + 1) * np.array(det_index_mask) for detector in detector_list: if detector > 0: image = image + _backproject(calibrated_event_list, detector=detector, pixel_size=pixel_size.value, image_dim=image_dim) dict_header = { "DATE-OBS": time_range.center.strftime("%Y-%m-%d %H:%M:%S"), "CDELT1": pixel_size[0], "NAXIS1": image_dim[0], "CRVAL1": xyoffset[0], "CRPIX1": image_dim[0] / 2 + 0.5, "CUNIT1": "arcsec", "CTYPE1": "HPLN-TAN", "CDELT2": pixel_size[1], "NAXIS2": image_dim[1], "CRVAL2": xyoffset[1], "CRPIX2": image_dim[0] / 2 + 0.5, "CUNIT2": "arcsec", "CTYPE2": "HPLT-TAN", "HGLT_OBS": 0, "HGLN_OBS": 0, "RSUN_OBS": sun.angular_radius(time_range.center).value, "RSUN_REF": sunpy.sun.constants.radius.value, "DSUN_OBS": sun.earth_distance(time_range.center).value * sunpy.sun.constants.au.value } result_map = sunpy.map.Map(image, dict_header) return result_map
def backprojection(calibrated_event_list, pixel_size: u.arcsec = (1., 1.) * u.arcsec, image_dim: u.pix = (64, 64) * u.pix): """ Given a stacked calibrated event list fits file create a back projection image. .. warning:: The image will not be in the right orientation. Parameters ---------- calibrated_event_list : `str` Filename of a RHESSI calibrated event list. pixel_size : `tuple`, optional A length 2 tuple with the size of the pixels in arcsecond `~astropy.units.Quantity`. Defaults to ``(1, 1) * u.arcsec``. image_dim : `tuple`, optional A length 2 tuple with the size of the output image in number of pixel `~astropy.units.Quantity` Defaults to ``(64, 64) * u.pix``. Returns ------- `sunpy.map.sources.RHESSImap` A backprojection map. """ # import sunpy.map in here so that net and timeseries don't end up importing map import sunpy.map pixel_size = pixel_size.to(u.arcsec) image_dim = np.array(image_dim.to(u.pix).value, dtype=int) afits = sunpy.io.read_file(calibrated_event_list) info_parameters = afits[2] xyoffset = info_parameters.data.field('USED_XYOFFSET')[0] time_range = TimeRange( info_parameters.data.field('ABSOLUTE_TIME_RANGE')[0], format='utime') image = np.zeros(image_dim) # find out what detectors were used det_index_mask = afits[1].data.field('det_index_mask')[0] detector_list = (np.arange(9) + 1) * np.array(det_index_mask) for detector in detector_list: if detector > 0: image = image + _backproject(calibrated_event_list, detector=detector, pixel_size=pixel_size.value, image_dim=image_dim) dict_header = { "DATE-OBS": time_range.center.strftime("%Y-%m-%d %H:%M:%S"), "CDELT1": pixel_size[0], "NAXIS1": image_dim[0], "CRVAL1": xyoffset[0], "CRPIX1": image_dim[0] / 2 + 0.5, "CUNIT1": "arcsec", "CTYPE1": "HPLN-TAN", "CDELT2": pixel_size[1], "NAXIS2": image_dim[1], "CRVAL2": xyoffset[1], "CRPIX2": image_dim[0] / 2 + 0.5, "CUNIT2": "arcsec", "CTYPE2": "HPLT-TAN", "HGLT_OBS": 0, "HGLN_OBS": 0, "RSUN_OBS": sun.angular_radius(time_range.center).value, "RSUN_REF": sunpy.sun.constants.radius.value, "DSUN_OBS": sun.earth_distance(time_range.center).value * sunpy.sun.constants.au.value } result_map = sunpy.map.Map(image, dict_header) return result_map