def test_solar_rotate_coordinate(): # Testing along the Sun-Earth line, observer is on the Earth obs_time = '2010-09-10 12:34:56' observer = get_earth(obs_time) c = SkyCoord(-570 * u.arcsec, 120 * u.arcsec, obstime=obs_time, observer=observer, frame=frames.Helioprojective) new_time = '2010-09-11 12:34:56' new_observer = get_earth(new_time) # Test that when both the observer and the time are specified, an error is raised. with pytest.raises(ValueError): d = solar_rotate_coordinate(c, observer=observer, time=new_time) # Test that the code properly filters the observer keyword with pytest.raises(ValueError): d = solar_rotate_coordinate(c, observer='earth') # Test that the code properly filters the time keyword with pytest.raises(ValueError): with pytest.warns( UserWarning, match="Using 'time' assumes an Earth-based observer"): d = solar_rotate_coordinate(c, time='noon') # Test that the code gives the same output for multiple different inputs # that define the same observer location and time. for i, definition in enumerate( (1 * u.day, TimeDelta(1 * u.day), new_time, new_observer)): if i in (0, 1, 2): with pytest.warns( UserWarning, match="Using 'time' assumes an Earth-based observer"): d = solar_rotate_coordinate(c, time=definition) else: d = solar_rotate_coordinate(c, observer=definition) # Test that a SkyCoordinate is created assert isinstance(d, SkyCoord) # Test the coordinate np.testing.assert_almost_equal(d.Tx.to(u.arcsec).value, -371.8885208634674, decimal=1) np.testing.assert_almost_equal(d.Ty.to(u.arcsec).value, 105.35006656251727, decimal=1) np.testing.assert_allclose(d.distance.to(u.km).value, 1.499642e+08, rtol=1e-5) # Test that the SkyCoordinate is Helioprojective assert isinstance(d.frame, frames.Helioprojective)
def track_ROI(init_submap, fullmap): """ :param init_submap: Subregion of map to crop :param fullmap: Map that is to be cropped :return: New coordinates for new map """ from sunpy.physics.differential_rotation import solar_rotate_coordinate # Subtract Time of current map to previous map rotated_coord = solar_rotate_coordinate(init_submap.center, fullmap.date) dlon = rotated_coord.Tx - init_submap.center.Tx dlat = rotated_coord.Ty - init_submap.center.Ty # Get new coordinates for box bl_new_lon = init_submap.bottom_left_coord.Tx + dlon bl_new_lat = init_submap.bottom_left_coord.Ty + dlat tr_new_lon = init_submap.top_right_coord.Tx + dlon tr_new_lat = init_submap.top_right_coord.Ty + dlat # Return the new box coordinates new_coords = [ bl_new_lon, tr_new_lon, bl_new_lat, tr_new_lat, ] # These are on arcsec quantities! return new_coords
def test_solar_rotate_coordinate(): # Testing along the Sun-Earth line, observer is on the Earth obstime = '2010-09-10 12:34:56' newtime = '2010-09-10 13:34:56' c = SkyCoord(-570*u.arcsec, 120*u.arcsec, obstime=obstime, observer=get_earth(obstime), frame=frames.Helioprojective) d = solar_rotate_coordinate(c, newtime) # Test that a SkyCoordinate is created assert isinstance(d, SkyCoord) # Test the coordinate np.testing.assert_almost_equal(d.Tx.to(u.arcsec).value, -562.3768, decimal=1) np.testing.assert_almost_equal(d.Ty.to(u.arcsec).value, 119.2684, decimal=1) np.testing.assert_almost_equal(d.distance.to(u.km).value, 150083151.97246578, decimal=1) # Test that the SkyCoordinate is Helioprojective assert isinstance(d.frame, frames.Helioprojective) # Test the observer assert d.observer.obstime == Time(parse_time(newtime), scale='utc') np.testing.assert_almost_equal(d.observer.lon.to(u.deg).value, 0.0, decimal=5) np.testing.assert_almost_equal(d.observer.lat.to(u.deg).value, 7.248, decimal=3) np.testing.assert_almost_equal(d.observer.radius.to(u.AU).value, 1.006954, decimal=6) assert isinstance(d.observer, frames.HeliographicStonyhurst)
def test_solar_rotate_coordinate(): # Testing along the Sun-Earth line, observer is on the Earth obstime = '2010-09-10 12:34:56' newtime = '2010-09-10 13:34:56' c = SkyCoord(-570*u.arcsec, 120*u.arcsec, obstime=obstime, observer=get_earth(obstime), frame=frames.Helioprojective) d = solar_rotate_coordinate(c, newtime) # Test that a SkyCoordinate is created assert isinstance(d, SkyCoord) # Test the coordinate np.testing.assert_almost_equal(d.Tx.to(u.arcsec).value, -562.3768, decimal=1) np.testing.assert_almost_equal(d.Ty.to(u.arcsec).value, 119.2684, decimal=1) np.testing.assert_almost_equal(d.distance.to(u.km).value, 150083151.97246578, decimal=1) # Test that the SkyCoordinate is Helioprojective assert isinstance(d.frame, frames.Helioprojective) # Test the observer assert d.observer.obstime == Time(parse_time(newtime), scale='utc') np.testing.assert_almost_equal(d.observer.lon.to(u.deg).value, 0.0, decimal=5) np.testing.assert_almost_equal(d.observer.lat.to(u.deg).value, 7.248, decimal=3) np.testing.assert_almost_equal(d.observer.radius.to(u.AU).value, 1.006954, decimal=6) assert isinstance(d.observer, frames.HeliographicStonyhurst)
def track_arcsec(refmap, fullmap): """ By Alexander James (UCL) Given a cropped reference map, will return the im cropped in a way that tracks solar rotation. Example: refmap = sunpy.map.Map(sfiles[0]) bottomleft_ref = [-500*u.arcsec, -600*u.arcsec] topright_ref = [0*u.arcsec, -200*u.arcsec] refmap = alexpy.submap(refmap, bottomleft_ref, topright_ref) fullmap = (sunpy.map.Map(sfile)) fullmap = track_arcsec(refmap, fullmap) """ from sunpy.physics.differential_rotation import solar_rotate_coordinate from astropy.coordinates import SkyCoord # Subtract Time of current map to previous map rotated_coord = solar_rotate_coordinate(refmap.center, fullmap.date) dlon = rotated_coord.Tx - refmap.center.Tx dlat = rotated_coord.Ty - refmap.center.Ty # Get new coordinated for box bl_new_lon = refmap.bottom_left_coord.Tx + dlon bl_new_lat = refmap.bottom_left_coord.Ty + dlat tr_new_lon = refmap.top_right_coord.Tx + dlon tr_new_lat = refmap.top_right_coord.Ty + dlat # Make new coordinates into new coord frame bl_new = SkyCoord(bl_new_lon, bl_new_lat, frame=fullmap.coordinate_frame) tr_new = SkyCoord(tr_new_lon, tr_new_lat, frame=fullmap.coordinate_frame) # Crop map to new location fullmap = fullmap.submap(bl_new, tr_new) # Give new, fixed map return fullmap
def rotate_SS(x_pos, y_pos, time1, time2): # Rotate centroid of SS for given times """Rotates centroid of a sunspot for given times Parameters ----------- x_pos, y_pos = centroid coordinates in pixel time1, time2 = datetime objects that indicate time of x_pos, y_pos (time1) and time to rotate sunspot to (time2) Returns ----------- new_x, new_y = estimated centroid position at time2 for sunspot ----------------------------------------------------------------- """ lon, lat = pixels_to_latlon(x_pos, y_pos) # convert to latlon hgx = astropy.units.Quantity(lon - 90., astropy.units.deg) hgy = astropy.units.Quantity(lat - 90., astropy.units.deg) start_coord = SkyCoord(hgx, hgy, frame=frames.HeliographicStonyhurst, obstime=time1) rotated_coord = solar_rotate_coordinate(start_coord, time2) new_lat = rotated_coord.lat.value + 90. new_lon = rotated_coord.lon.value + 90. new_x, new_y = latlon_to_pixels(new_lon, new_lat) return new_x, new_y
def map_rot_correct(mmap,refx,refy,reftime): """ Correct the solar rotation. Parameters ---------- mmap : sunpy.map.GenericMap Single map class. refx : astropy.units.Quantity Horizontal wcs information of reference frame. refy : astropy.units.Quantity Vertical wcs information of reference frame. reftime : astropy.time.Time Time for the reference frame. Returns ------- smap : sunpy.map.GenericMap Solar rotation corrected map class. """ refc = SkyCoord(refx, refy, obstime= reftime, observer= get_earth(reftime), frame= frames.Helioprojective) date = mmap.date res = solar_rotate_coordinate(refc, date ,frame_time= 'synodic') x = res.Tx.value y = res.Ty.value sx = x - refx.value sy = y - refy.value smap = mmap.shift(-sx,-sy) return smap
def test_consistency_with_rotatedsunframe(): old_observer = frames.HeliographicStonyhurst(10 * u.deg, 20 * u.deg, 1 * u.AU, obstime='2001-01-01') new_observer = frames.HeliographicStonyhurst(30 * u.deg, 40 * u.deg, 2 * u.AU, obstime='2001-01-08') hpc_coord = SkyCoord(100 * u.arcsec, 200 * u.arcsec, frame='helioprojective', observer=old_observer, obstime=old_observer.obstime) # Perform the differential rotation using solar_rotate_coordinate() result1 = solar_rotate_coordinate(hpc_coord, observer=new_observer) # Perform the differential rotation using RotatedSunFrame, with translational motion of the Sun # ignored using transform_with_sun_center() rsf_coord = RotatedSunFrame(base=hpc_coord, rotated_time=new_observer.obstime) with transform_with_sun_center(): result2 = rsf_coord.transform_to(result1.replicate_without_data()) assert_quantity_allclose(result1.Tx, result2.Tx) assert_quantity_allclose(result1.Ty, result2.Ty) assert_quantity_allclose(result1.distance, result2.distance)
def rotate_coord(map, coord, date): coord_sc = SkyCoord([(float(v[1]), float(v[0])) * u.deg for v in np.array(coord)], obstime=date, frame=frames.HeliographicCarrington) coord_sc = coord_sc.transform_to(frames.Helioprojective) rotated_coord_sc = solar_rotate_coordinate(coord_sc, map.date) px = map.world_to_pixel(rotated_coord_sc) return [(int(px.x[i].value), int(px.y[i].value)) for i in range(len(px.x))]
def sub_window(self): #3 color image if self.color3: self.scale = [self.img.scale[0].value, self.img.scale[1].value] # get x, y image scale #single color image else: self.scale = [self.img.scale[0].value, self.img.scale[1].value] # get x, y image scale #if rotation set get modify cx and cy values if self.rotation: #make rotation stable across different sunpy version #try: # from sunpy.physics.differential_rotation import rot_hpc #except ImportError: #forcing sunpy > 8.0 from sunpy.physics.differential_rotation import solar_rotate_coordinate #use astropy SkyCoord from astropy.coordinates import SkyCoord #get frame for coordiantes from sunpy.coordinates import frames import astropy.units as u #create Sky Coord class with intial values c = SkyCoord(self.cx * u.arcsec, self.cy * u.arcsec, obstime=self.rot_time, frame=frames.Helioprojective) #rotate start points nc = solar_rotate_coordinate(c, self.obs_time) #update with new rotation values self.cx, self.cy = nc.Tx.value, nc.Ty.value #set new plot limits #flip x and y values if h0>w0 if self.flip_image: self.xlim = [ self.cy - (self.scale[0] * self.w0 / 2.), self.cy + (self.scale[0] * self.w0 / 2.) ] self.ylim = [ self.cx - (self.scale[1] * self.h0 / 2.), self.cx + (self.scale[1] * self.h0 / 2.) ] else: self.xlim = [ self.cx - (self.scale[0] * self.w0 / 2.), self.cx + (self.scale[0] * self.w0 / 2.) ] self.ylim = [ self.cy - (self.scale[1] * self.h0 / 2.), self.cy + (self.scale[1] * self.h0 / 2.) ]
def rot_hpc(xs, ys, start, end, rot_type='meaningless'): #xs, ys = calc_poly_values(coor) #update deprecated function J. Prchlik 2017/11/03 c = SkyCoord(xs, ys, obstime=start, frame=frames.Helioprojective) #rotate start points to end time nc = solar_rotate_coordinate(c, end) #split into x and y rotx, roty = nc.Tx, nc.Ty #return rotated coordinates return rotx, roty
def test_solar_rotate_coordinate(): # Testing along the Sun-Earth line, observer is on the Earth obs_time = '2010-09-10 12:34:56' observer = get_earth(obs_time) c = SkyCoord(-570*u.arcsec, 120*u.arcsec, obstime=obs_time, observer=observer, frame=frames.Helioprojective) new_time = '2010-09-11 12:34:56' new_observer = get_earth(new_time) # Test that when both the observer and the time are specified, an error is raised. with pytest.raises(ValueError): d = solar_rotate_coordinate(c, observer=observer, time=new_time) # Test that the code properly filters the observer keyword with pytest.raises(ValueError): d = solar_rotate_coordinate(c, observer='earth') # Test that the code properly filters the time keyword with pytest.raises(ValueError): d = solar_rotate_coordinate(c, time='noon') # Test that the code gives the same output for multiple different inputs # that define the same observer location and time. for i, definition in enumerate((1 * u.day, TimeDelta(1*u.day), new_time, new_observer)): if i in (0, 1, 2): d = solar_rotate_coordinate(c, time=definition) else: d = solar_rotate_coordinate(c, observer=definition) # Test that a SkyCoordinate is created assert isinstance(d, SkyCoord) # Test the coordinate np.testing.assert_almost_equal(d.Tx.to(u.arcsec).value, -371.8885208634674, decimal=1) np.testing.assert_almost_equal(d.Ty.to(u.arcsec).value, 105.35006656251727, decimal=1) np.testing.assert_allclose(d.distance.to(u.km).value, 1.499642e+08, rtol=1e-5) # Test that the SkyCoordinate is Helioprojective assert isinstance(d.frame, frames.Helioprojective)
def astro_track_ROI(ref_map, newmap, observer, large_roi): """ This is a knock-off version to calculate movement for a given amount of time. Use SUNPY? :param ref_map: Subregion of map to crop :param newmap: Map that is to be cropped :param large_roi: Large roi_ref :return: New coordinates for new map """ import datetime from sunpy.physics.differential_rotation import solar_rotate_coordinate from astropy.coordinates import SkyCoord t_ref = datetime.datetime.strptime(ref_map.fits_header["DATE-OBS"], "%Y-%m-%dT%H:%M:%S.%f") t_new = datetime.datetime.strptime(newmap.fits_header["DATE-OBS"], "%Y-%m-%dT%H:%M:%S.%f") x_0 = large_roi[0] x_f = large_roi[1] y_0 = large_roi[2] y_f = large_roi[3] dx = x_f - x_0 dy = y_f - y_0 center_x, center_y = dx / 2 + x_0, dy / 2 + y_0 start_coord = SkyCoord(center_x, center_y, frame="helioprojective", obstime=t_ref, observer=observer) rotated_center = solar_rotate_coordinate(start_coord, time=t_new) new_coords = [ rotated_center.Tx - dx / 2, rotated_center.Tx + dx / 2, rotated_center.Ty - dy / 2, rotated_center.Ty + dy / 2, ] return new_coords
############################################################################## # Let's define how many days in the future we want to rotate to. dt = TimeDelta(4 * u.day) future_date = aia_map.date + dt ############################################################################## # Now let's plot the original and rotated positions on the AIA map. fig = plt.figure() ax = fig.add_subplot(projection=aia_map) aia_map.plot(axes=ax, clip_interval=(1, 99.99) * u.percent) ax.set_title('The effect of {} days of differential rotation'.format( dt.to(u.day).value)) aia_map.draw_grid(axes=ax) for this_hpc_x, this_hpc_y in zip(hpc_x, hpc_y): start_coord = SkyCoord(this_hpc_x, this_hpc_y, frame=aia_map.coordinate_frame) rotated_coord = solar_rotate_coordinate(start_coord, time=future_date) coord = SkyCoord([start_coord.Tx, rotated_coord.Tx], [start_coord.Ty, rotated_coord.Ty], frame=aia_map.coordinate_frame) ax.plot_coord(coord, 'o-') ax.set_ylim(0, aia_map.data.shape[1]) ax.set_xlim(0, aia_map.data.shape[0]) plt.show()
def calculate_solar_rotate_shift(mc, layer_index=0, **kwargs): """ Calculate the shift that must be applied to each map contained in 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. Parameters ---------- 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.differential_rotation.solar_rotate_coordinate`. 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 arcseconds as understood in helioprojective coordinates systems. """ # 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) # Layer that rotate_to_this_layer = mc.maps[layer_index] # 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". new_coordinate = solar_rotate_coordinate( m.center, rotate_to_this_layer.date, new_observer_location=rotate_to_this_layer.observer_coordinate, **kwargs) # Calculate the shift in arcseconds xshift_arcseconds[ i] = new_coordinate.Tx - rotate_to_this_layer.center.Tx yshift_arcseconds[ i] = new_coordinate.Ty - rotate_to_this_layer.center.Ty return {"x": xshift_arcseconds, "y": yshift_arcseconds}
PRINTER.display_item("Initial time", INIT_TIME) ######################### INIT_LOC = SkyCoord(INIT_COORD.Tx, INIT_COORD.Ty, obstime = INIT_TIME, observer = get_earth(INIT_TIME), frame = frames.Helioprojective) PRINTER.display_item("Initial location", "(%s arcsec, %s arcsec)" % (INIT_LOC.Tx, INIT_LOC.Ty)) ######################### PRINTER.info_text("Calculating future coordinates") LOCS = [solar_rotate_coordinate(INIT_LOC, MAPCUBE[i].date) for i in range(len(MAPCUBE))] ######################### if ask_to_change_default_settings: if(PRINTER.input_text("Use default settings (low scale 0, high scale 40000)? [y/n]") == "n"): default_low_scale = int(PRINTER.input_text("Enter low scale")) default_high_scale = int(PRINTER.input_text("Enter high scale")) ######################### if not only_fulldisk_images: if not auto_sel: coord1 = MAPCUBE[0].pixel_to_world(x1, y1)
############################################################################## # Now let's get the boundary of the coronal hole ch = responses[response_index] p1 = ch["hpc_boundcc"][9:-2] p2 = p1.split(',') p3 = [v.split(" ") for v in p2] ch_date = parse_time(ch['event_starttime']) ############################################################################## # The coronal hole was detected at a certain time. To plot it on a map, we # need to rotate it to the map observation time. ch_boundary = SkyCoord( [(float(v[0]), float(v[1])) * u.arcsec for v in p3], obstime=ch_date, frame=frames.Helioprojective) rotated_ch_boundary = solar_rotate_coordinate(ch_boundary, aia_map.date) ############################################################################## # Now let's plot the rotated coronal hole boundary on the AIA map, and fill # it with some matplotlib hatching. fig = plt.figure() ax = plt.subplot(projection=aia_map) aia_map.plot(axes=ax) ax.plot_coord(rotated_ch_boundary, color='c') ax.set_title('{:s}\n{:s}'.format(aia_map.name, ch['frm_specificid'])) plt.colorbar() plt.show()
def plot_rotation(self, start, coor, dh=0, color='teal', linestyle='-', alpha=1.0, ids=None): """ plot_rotation overplots a h alpha filament track accounting for solar roation The function plot_rotation uses the current image time to correct the track observation time for solar rotation. To correct for rotation the function uses the solar_rotation module from sunpy Parameters ---------- start: datetime object start is the observed time of the track. coor : str coor is the polygon string for the track's shape. dh : datetime object dh is deprecated, thus no longer used by plot_rotation (default = 0) color: str color is the numpy string color to used for outlining the track (default = 'red'). linestyle: str linstyle is the matplotlib string to use for the line (default = '-') alpha: float alpha is the opacity of the line to plot (default = 0.5, range = [0.0,1.0]) Returns ------- self """ xs, ys = self.calc_poly_values(coor) #calculate the mean position #stopx, stopy = solar_rotation.rot_hpc(xs*u.arcsec,ys*u.arcsec,start,self.stop) #update deprecated function J. Prchlik 2017/11/03 c = SkyCoord(xs * u.arcsec, ys * u.arcsec, obstime=start, frame=frames.Helioprojective) #rotate start points to end time nc = solar_rotate_coordinate(c, self.stop) #get rid of units stopx, stopy = nc.Tx.value, nc.Ty.value self.ax.plot(stopx, stopy, linestyle=linestyle, color=color, zorder=500, alpha=alpha, linewidth=3) self.ax.text(np.mean(stopx), np.max(stopy), str(ids), alpha=1., color=color, fontweight='bold')
def update_fiss_header(file,alignfile,**kwargs): """ Create the new FISS data with update header. Parameters ---------- file : list FISS fts file list alignfile : str Aligned information binary (.npz) file. sil : (optional) bool If False, it print the ongoing time index. * Default is True. sol_rot : (optional) bool If True, correct the solar rotation when update the file header. * Default is False. Returns ------- mfts : file List of files which updated the header. Notes ----- Name of saved fits data file is added 'm' to the first character of original data name. """ sil=kwargs.pop('sil',False) sol_rot=kwargs.pop('sol_rot',False) if not sil: print('Add the align information to the haeder.') level=alignfile[-8:-4] inform=np.load(alignfile) fissht=[getheader(i) for i in file] fissh=[fits.getheader(i) for i in file] tlist=[i['date'] for i in fissht] time=Time(tlist,format='isot',scale='ut1') angle=inform['angle'] ny=fissht[0]['naxis2'] nx=fissht[0]['naxis3'] x=np.array((0,nx-1,nx-1,0)) y=np.array((0,0,ny-1,ny-1)) xc=inform['xc'].item() yc=inform['yc'].item() dx=inform['dx'] dy=inform['dy'] xt1,yt1=rot_trans(x,y,xc,yc,angle.max()) xt2,yt2=rot_trans(x,y,xc,yc,angle.min()) tmpx=np.concatenate((xt1,xt2)) tmpy=np.concatenate((yt1,yt2)) xmargin=int(np.abs(np.round(tmpx.min()+dx.min())))+1 ymargin=int(np.abs(np.around(tmpy.min()+dy.min())))+1 if level=='lev0': for i,h in enumerate(fissh): h['alignl']=(0,'Alignment level') h['reflect']=(False,'Mirror reverse') h['reffr']=(inform['reffr'].item(),'Reference frame in alignment') h['reffi']=(inform['reffi'].item(),'Reference file name in alignment') h['cdelt2']=(0.16,'arcsec per pixel') h['cdelt3']=(0.16,'arcsec per pixel') h['crota2']=(angle[i], 'Roation angle about reference pixel') h['crpix3']=(inform['xc'].item(),'Reference pixel in data axis 3') h['shift3']=(inform['dx'][i], 'Shifting pixel value along data axis 2') h['crpix2']=(inform['yc'].item(),'Reference pixel in data axis 2') h['shift2']=(inform['dy'][i], 'Shifting pixel value along data axis 3') h['margin2']=(ymargin,'Rotation margin in axis 2') h['margin3']=(xmargin,'Rotation margin in axis 3') h['history']='FISS aligned (lev0)' elif level=='lev1': wcsx=inform['wcsx'] wcsy=inform['wcsy'] xref=wcsx*u.arcsec yref=wcsy*u.arcsec reffr=inform['reffr'] for i,h in enumerate(fissh): if sol_rot: refc = SkyCoord(xref, yref, obstime = time[reffr], observer= get_earth(time[reffr]), frame= frames.Helioprojective) res = solar_rotate_coordinate(refc, time[i], frame_time= 'synodic') wcsx = res.Tx.value wcsy = res.Ty.value h['crval3']=(wcsx.value, 'Location of ref pixel x (arcsec)') h['crval2']=(wcsy.value, 'Location of ref pixel y (arcsec)') else: h['crval3']=(wcsx.item(), 'Location of ref pixel for ref frame x (arcsec)') h['crval2']=(wcsy.item(), 'Location of ref pixel for ref frame y (arcsec)') h['alignl']=(1,'Alignment level') h['reflect']=(inform['reflect'].item(),'Mirror reverse') h['reffr']=(inform['reffr'].item(),'Reference frame in alignment') h['reffi']=(inform['reffi'].item(),'Reference file name in alignment') h['cdelt2']=(0.16,'arcsec per pixel') h['cdelt3']=(0.16,'arcsec per pixel') h['crota1']=(inform['sdo_angle'].item(), 'Rotation angle of reference frame (radian)') h['crota2']=(inform['angle'][i], 'Rotation angle about reference pixel (radian)') h['crpix3']=(inform['xc'].item(),'Reference pixel in data axis 3') h['shift3']=(inform['dx'][i], 'Shifting pixel value along data axis 3') h['crpix2']=(inform['yc'].item(),'Reference pixel in data axis 2') h['shift2']=(inform['dy'][i], 'Shifting pixel value along data axis 2') h['margin2']=(ymargin,'Rotation margin in axis 2') h['margin3']=(xmargin,'Rotation margin in axis 3') h['srot']=(True,'Solar Rotation correction') h['history']='FISS aligned and matched wcs (lev1)' else: raise ValueError('The level of alignfile is neither lev0 or lev1.') data=[fits.getdata(i) for i in file] odirname=os.path.dirname(file[0]) if not odirname: odirname=os.getcwd() dirname = os.path.join(odirname, 'match') try: os.mkdir(dirname) except: pass for i,oname in enumerate(file): name='m'+os.path.basename(oname) fits.writeto(os.path.join(dirname, name),data[i],fissh[i]) try: pfilelist=[i['pfile'] for i in fissh] pfileset=set(pfilelist) for i in pfileset: copy2(os.path.join(odirname, i),os.path.join(dirname,i)) except: pass if not sil: print("The align information is updated to the header, " "and new fts file is locate %s the file name is 'mFISS*.fts'"%dirname)
hpc_y = u.Quantity(np.arange(-700, 800, 100), u.arcsec) hpc_x = np.zeros_like(hpc_y) ############################################################################## # Let's define how many days in the future we want to rotate to dt = timedelta(days=4) future_date = aia_map.date + dt ############################################################################## # Now let's plot the original and rotated positions on the AIA map. fig = plt.figure() ax = plt.subplot(projection=aia_map) aia_map.plot() ax.set_title('The effect of {0} days of differential rotation'.format(dt.days)) aia_map.draw_grid() for this_hpc_x, this_hpc_y in zip(hpc_x, hpc_y): start_coord = SkyCoord(this_hpc_x, this_hpc_y, frame=aia_map.coordinate_frame) rotated_coord = solar_rotate_coordinate(start_coord, future_date) coord = SkyCoord([start_coord.Tx, rotated_coord.Tx], [start_coord.Ty, rotated_coord.Ty], frame=aia_map.coordinate_frame) ax.plot_coord(coord, 'o-') plt.ylim(0, aia_map.data.shape[1]) plt.xlim(0, aia_map.data.shape[0]) plt.show()
area = response['area_atdiskcenter'] response_index = i ############################################################################## # Next let's get the boundary of the coronal hole ch = responses[response_index] p1 = ch["hpc_boundcc"][9:-2] p2 = p1.split(',') p3 = [v.split(" ") for v in p2] ch_date = parse_time(ch['event_starttime']) ############################################################################## # The coronal hole was detected at different time than the AIA image was # taken so we need to rotate it to the map observation time. ch_boundary = SkyCoord([(float(v[0]), float(v[1])) * u.arcsec for v in p3], obstime=ch_date, observer="earth", frame=frames.Helioprojective) rotated_ch_boundary = solar_rotate_coordinate(ch_boundary, time=aia_map.date) ############################################################################## # Now let's plot the rotated coronal hole boundary on the AIA map, and fill # it with hatching. fig = plt.figure() ax = plt.subplot(projection=aia_map) aia_map.plot(axes=ax, clip_interval=(1, 99.99) * u.percent) ax.plot_coord(rotated_ch_boundary, color='c') ax.set_title('{:s}\n{:s}'.format(aia_map.name, ch['frm_specificid'])) plt.colorbar() plt.show()
def calculate_solar_rotate_shift(mc, layer_index=0, **kwargs): """ Calculate the shift that must be applied to each map contained in a mapsequence in order to compensate for solar rotation. The center of the map is used to calculate the position of each mapsequence layer. Shifts are calculated relative to a specified layer in the mapsequence. 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 mapsequence, animate the derotated mapsequence, 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. Parameters ---------- mc : `sunpy.map.MapSequence` The input mapsequence. 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.differential_rotation.solar_rotate_coordinate`. Returns ------- x, y : `~astropy.units.Quantity`, ~astropy.units.Quantity` The shifts relative to the index layer that can be applied to the input mapsequence in order to compensate for solar rotation. The shifts are given in arcseconds as understood in helioprojective coordinates systems. """ # 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) # Layer that rotate_to_this_layer = mc.maps[layer_index] # 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". new_coordinate = solar_rotate_coordinate(m.center, observer=rotate_to_this_layer.observer_coordinate, **kwargs) # Calculate the shift in arcseconds xshift_arcseconds[i] = new_coordinate.Tx - rotate_to_this_layer.center.Tx yshift_arcseconds[i] = new_coordinate.Ty - rotate_to_this_layer.center.Ty return {"x": xshift_arcseconds, "y": yshift_arcseconds}