correct a bug where rotation doesn't update header when wcs.pc is identity

This commit is contained in:
Thibault Barnouin
2022-07-11 17:36:30 +02:00
parent 2c5d4212ac
commit e61984ae3d
55 changed files with 161 additions and 161 deletions

View File

@@ -52,25 +52,20 @@ def get_obs_data(infiles, data_folder="", compute_flux=False):
new_wcs = wcs.WCS(header).deepcopy()
if new_wcs.wcs.has_cd() or (new_wcs.wcs.cdelt == np.array([1., 1.])).all():
# Update WCS with relevant information
HST_aper = 2400. # HST aperture in mm
f_ratio = header['f_ratio']
px_dim = np.array([25., 25.]) # Pixel dimension in µm
if header['pxformt'].lower() == 'zoom':
px_dim[0] = 50.
#new_cdelt = 206.3/3600.*px_dim/(f_ratio*HST_aper)
new_cdelt = np.abs(np.linalg.eig(new_wcs.wcs.cd)[0])
if new_wcs.wcs.has_cd():
old_cd = new_wcs.wcs.cd
del new_wcs.wcs.cd
keys = list(new_wcs.to_header().keys())+['CD1_1','CD1_2','CD2_1','CD2_2']
for key in keys:
header.remove(key, ignore_missing=True)
new_cdelt = np.linalg.eig(old_cd)[0]
elif (new_wcs.wcs.cdelt == np.array([1., 1.])).all() and \
(new_wcs.array_shape in [(512, 512),(1024,512),(512,1024),(1024,1024)]):
old_cd = new_wcs.wcs.pc
new_wcs.wcs.pc = np.dot(old_cd, np.diag(1./new_cdelt))
new_wcs.wcs.cdelt = new_cdelt
header.update(new_wcs.to_header())
for key, val in new_wcs.to_header().items():
header[key] = val
if compute_flux:
for i in range(len(infiles)):

View File

@@ -462,8 +462,8 @@ class align_maps(object):
data = self.map[0].data
other_data = self.other_map[0].data
plt.rcParams.update({'font.size': 16})
self.fig = plt.figure(figsize=(25,15))
plt.rcParams.update({'font.size': 10})
self.fig = plt.figure(figsize=(10,10))
#Plot the UV map
self.ax1 = self.fig.add_subplot(121, projection=self.wcs_map)
self.ax1.set_facecolor('k')
@@ -522,8 +522,10 @@ class align_maps(object):
#Selection button
self.axapply = self.fig.add_axes([0.80, 0.01, 0.1, 0.04])
self.bapply = Button(self.axapply, 'Apply reference')
self.bapply.label.set_fontsize(8)
self.axreset = self.fig.add_axes([0.60, 0.01, 0.1, 0.04])
self.breset = Button(self.axreset, 'Leave as is')
self.breset.label.set_fontsize(8)
def get_aligned_wcs(self):
return self.wcs_map, self.wcs_other
@@ -751,7 +753,8 @@ class overplot_pol(align_maps):
class align_pol(object):
def __init__(self, maps, **kwargs):
maps = np.array(maps)
order = np.argsort(np.array([curr[0].header['mjd-obs'] for curr in maps]))
maps = np.array(maps)[order]
self.ref_map, self.other_maps = maps[0], maps[1:]
self.wcs = WCS(self.ref_map[0].header)
@@ -797,13 +800,16 @@ class align_pol(object):
plt.rcdefaults()
fig = plt.figure(figsize=(10,10))
ax = fig.add_subplot(111, projection=wcs)
ax.set(xlabel="Right Ascension (J2000)", ylabel="Declination (J2000)", facecolor='k')
ax.set(xlabel="Right Ascension (J2000)", ylabel="Declination (J2000)", facecolor='k',
title="target {0:s} observed on {1:s}".format(curr_map[0].header['targname'], curr_map[0].header['date-obs']))
fig.subplots_adjust(hspace=0, wspace=0, right=0.9)
cbar_ax = fig.add_axes([0.95, 0.12, 0.01, 0.75])
if not ax_lim is None:
lim = np.concatenate([wcs.world_to_pixel(ax_lim[i]) for i in range(len(ax_lim))])
x_lim, y_lim = lim[0::2], lim[1::2]
print(x_lim[0], y_lim[0], wcs.pixel_to_world(x_lim[0], y_lim[0]))
print(x_lim[1], y_lim[1], wcs.pixel_to_world(x_lim[1], y_lim[1]))
ax.set(xlim=x_lim,ylim=y_lim)
if v_lim is None:
@@ -856,9 +862,11 @@ class align_pol(object):
vmin, vmax = np.min([vmin, np.min(self.ref_map[0].data[self.ref_map[0].data > 0.])]), np.max([vmax, np.max(self.ref_map[0].data[self.ref_map[0].data > 0.])])
v_lim = np.array([vmin, vmax])
fig, ax = self.single_plot(self.ref_map, self.wcs, v_lim = v_lim, SNRp_cut=SNRp_cut, SNRi_cut=SNRi_cut, savename=savename, **kwargs)
fig, ax = self.single_plot(self.ref_map, self.wcs, v_lim = v_lim, SNRp_cut=SNRp_cut, SNRi_cut=SNRi_cut, savename=savename+'_0', **kwargs)
x_lim, y_lim = ax.get_xlim(), ax.get_ylim()
ax_lim = np.array([self.wcs.pixel_to_world(x_lim[i], y_lim[i]) for i in range(len(x_lim))])
print(x_lim[0], y_lim[0], ax_lim[0])
print(x_lim[1], y_lim[1], ax_lim[1])
for i, curr_map in enumerate(self.other_maps):
self.single_plot(curr_map, self.wcs_other[i], v_lim=v_lim, ax_lim=ax_lim, SNRp_cut=SNRp_cut, SNRi_cut=SNRi_cut, savename=savename+'_'+str(i+1), **kwargs)

View File

@@ -651,7 +651,7 @@ def rebin_array(data_array, error_array, headers, pxsize, scale,
if scale.lower() in ['px', 'pixel']:
Dxy = np.array([pxsize,]*2)
elif scale.lower() in ['arcsec','arcseconds']:
Dxy = np.floor(pxsize/w.wcs.cdelt/3600.).astype(int)
Dxy = np.floor(pxsize/np.abs(w.wcs.cdelt)/3600.).astype(int)
elif scale.lower() in ['full','integrate']:
Dxy = np.floor(image.shape).astype(int)
else:
@@ -1389,7 +1389,7 @@ def compute_pol(I_stokes, Q_stokes, U_stokes, Stokes_cov, headers):
def rotate_Stokes(I_stokes, Q_stokes, U_stokes, Stokes_cov, data_mask, headers,
ang, SNRi_cut=None):
ang=None, SNRi_cut=None):
"""
Use scipy.ndimage.rotate to rotate I_stokes to an angle, and a rotation
matrix to rotate Q, U of a given angle in degrees and update header
@@ -1411,9 +1411,10 @@ def rotate_Stokes(I_stokes, Q_stokes, U_stokes, Stokes_cov, data_mask, headers,
2D boolean array delimiting the data to work on.
headers : header list
List of headers corresponding to the reduced images.
ang : float
ang : float, optional
Rotation angle (in degrees) that should be applied to the Stokes
parameters
parameters. If None, will rotate to have North up.
Defaults to None.
SNRi_cut : float, optional
Cut that should be applied to the signal-to-noise ratio on I.
Any SNR < SNRi_cut won't be displayed. If None, cut won't be applied.
@@ -1450,6 +1451,11 @@ def rotate_Stokes(I_stokes, Q_stokes, U_stokes, Stokes_cov, data_mask, headers,
U_stokes[i,j] = eps*np.sqrt(Stokes_cov[2,2][i,j])
#Rotate I_stokes, Q_stokes, U_stokes using rotation matrix
if ang is None:
ang = np.zeros((len(headers),))
for i,head in enumerate(headers):
ang[i] = -head['orientat']
ang = ang.mean()
alpha = ang*np.pi/180.
mrot = np.array([[1., 0., 0.],
[0., np.cos(2.*alpha), np.sin(2.*alpha)],
@@ -1490,33 +1496,22 @@ def rotate_Stokes(I_stokes, Q_stokes, U_stokes, Stokes_cov, data_mask, headers,
#Update headers to new angle
new_headers = []
mrot = np.array([[np.cos(-alpha), -np.sin(-alpha)],
[np.sin(-alpha), np.cos(-alpha)]])
[np.sin(-alpha), np.cos(-alpha)]])
for header in headers:
new_header = deepcopy(header)
new_header['orientat'] = header['orientat'] + ang
new_wcs = WCS(header).deepcopy()
if new_wcs.wcs.has_cd(): # CD matrix
# Update WCS with relevant information
HST_aper = 2400. # HST aperture in mm
f_ratio = header['f_ratio']
px_dim = np.array([25., 25.]) # Pixel dimension in µm
if ref_header['pxformt'].lower() == 'zoom':
px_dim[0] = 50.
#new_cdelt = 206.3/3600.*px_dim/(f_ratio*HST_aper)
new_cdelt = np.abs(np.linalg.eig(new_wcs.wcs.cd)[0])
old_cd = new_wcs.wcs.cd
del new_wcs.wcs.cd
keys = ['CD1_1','CD1_2','CD2_1','CD2_2']
for key in keys:
new_header.remove(key, ignore_missing=True)
new_wcs.wcs.pc = np.dot(mrot, np.dot(old_cd, np.diag(1./new_cdelt)))
new_wcs.wcs.cdelt = new_cdelt
elif new_wcs.wcs.has_pc(): # PC matrix + CDELT
newpc = np.dot(mrot, new_wcs.wcs.get_pc())
new_wcs.wcs.pc = newpc
new_wcs.wcs.pc = np.dot(mrot, new_wcs.wcs.pc)
print(new_wcs.wcs.pc)
new_wcs.wcs.crpix = np.dot(mrot, new_wcs.wcs.crpix - old_center[::-1]) + new_center[::-1]
new_wcs.wcs.set()
new_header.update(new_wcs.to_header())
for key, val in new_wcs.to_header().items():
new_header.set(key,val)
if new_wcs.wcs.pc[0,0] == 1.:
new_header.set('PC1_1',1.)
if new_wcs.wcs.pc[1,1] == 1.:
new_header.set('PC2_2',1.)
new_headers.append(new_header)
@@ -1619,33 +1614,18 @@ def rotate_data(data_array, error_array, data_mask, headers, ang):
#Update headers to new angle
new_headers = []
mrot = np.array([[np.cos(-alpha), -np.sin(-alpha)],
[np.sin(-alpha), np.cos(-alpha)]])
[np.sin(-alpha), np.cos(-alpha)]])
for header in headers:
new_header = deepcopy(header)
new_header['orientat'] = header['orientat'] + ang
new_wcs = WCS(header).deepcopy()
if new_wcs.wcs.has_cd(): # CD matrix
# Update WCS with relevant information
HST_aper = 2400. # HST aperture in mm
f_ratio = ref_header['f_ratio']
px_dim = np.array([25., 25.]) # Pixel dimension in µm
if ref_header['pxformt'].lower() == 'zoom':
px_dim[0] = 50.
new_cdelt = 206.3/3600.*px_dim/(f_ratio*HST_aper)
old_cd = new_wcs.wcs.cd
del new_wcs.wcs.cd
keys = ['CD1_1','CD1_2','CD2_1','CD2_2']
for key in keys:
new_header.remove(key, ignore_missing=True)
new_wcs.wcs.pc = np.dot(mrot, np.dot(old_cd, np.diag(1./new_cdelt)))
new_wcs.wcs.cdelt = new_cdelt
elif new_wcs.wcs.has_pc(): # PC matrix + CDELT
newpc = np.dot(mrot, new_wcs.wcs.get_pc())
new_wcs.wcs.pc = newpc
new_wcs.wcs.pc = np.dot(mrot, new_wcs.wcs.pc)
new_wcs.wcs.crpix = np.dot(mrot, new_wcs.wcs.crpix - old_center[::-1]) + new_center[::-1]
new_wcs.wcs.set()
new_header.update(new_wcs.to_header())
for key, val in new_wcs.to_header().items():
new_header[key] = val
new_headers.append(new_header)
globals()['theta'] = theta - alpha