fix WCS computation when importing fits

This commit is contained in:
2025-04-10 18:14:38 +02:00
parent 3c321a7724
commit 278a31beab
2 changed files with 55 additions and 32 deletions

View File

@@ -16,7 +16,7 @@ from astropy.io import fits
from astropy.wcs import WCS from astropy.wcs import WCS
from .convex_hull import clean_ROI from .convex_hull import clean_ROI
from .utils import wcs_PA from .utils import wcs_CD_to_PC, wcs_PA
def get_obs_data(infiles, data_folder="", compute_flux=False): def get_obs_data(infiles, data_folder="", compute_flux=False):
@@ -61,26 +61,30 @@ def get_obs_data(infiles, data_folder="", compute_flux=False):
for i in range(len(data_array)): for i in range(len(data_array)):
data_array[i][data_array[i] < 0.0] = 0.0 data_array[i][data_array[i] < 0.0] = 0.0
# force WCS to convention PCi_ja unitary, cdelt in deg # Compute CDELT, ORIENTAT from header
for wcs, header in zip(wcs_array, headers): for wcs, header in zip(wcs_array, headers):
new_wcs = wcs.deepcopy() new_wcs = wcs.deepcopy()
if new_wcs.wcs.has_cd() or (new_wcs.wcs.cdelt[:2] == np.array([1.0, 1.0])).all(): if new_wcs.wcs.has_cd():
# Update WCS with relevant information del new_wcs.wcs.cd
if new_wcs.wcs.has_cd(): keys = list(new_wcs.to_header().keys()) + ["CD1_1", "CD1_2", "CD1_3", "CD2_1", "CD2_2", "CD2_3", "CD3_1", "CD3_2", "CD3_3"]
del new_wcs.wcs.cd for key in keys:
keys = list(new_wcs.to_header().keys()) + ["CD1_1", "CD1_2", "CD1_3", "CD2_1", "CD2_2", "CD2_3", "CD3_1", "CD3_2", "CD3_3"] header.remove(key, ignore_missing=True)
for key in keys: cdelt, orient = wcs_CD_to_PC(wcs.wcs.cd)
header.remove(key, ignore_missing=True) new_wcs.wcs.pc = wcs.wcs.cd.dot(np.diag(1.0 / cdelt))
new_cdelt = np.linalg.eigvals(wcs.wcs.cd) new_wcs.wcs.cdelt = cdelt
# new_cdelt.sort() try:
new_wcs.wcs.pc = wcs.wcs.cd.dot(np.diag(1.0 / new_cdelt)) header["ORIENTAT"] = float(header["ORIENTAT"])
new_wcs.wcs.cdelt = new_cdelt except KeyError:
for key, val in new_wcs.to_header().items(): header["ORIENTAT"] = -orient
header[key] = val elif new_wcs.wcs.has_pc() and (new_wcs.wcs.cdelt[:2] != np.array([1.0, 1.0])).all():
try: try:
header["ORIENTAT"] = float(header["ORIENTAT"]) header["ORIENTAT"] = float(header["ORIENTAT"])
except KeyError: except KeyError:
header["ORIENTAT"] = wcs_PA(new_wcs.wcs.pc[1, 0], np.diag(new_wcs.wcs.pc).mean()) header["ORIENTAT"] = -wcs_PA(new_wcs.wcs.pc, new_wcs.wcs.cdelt)
else:
print("Could not compute ORIENTAT or CDELT from WCS")
for key, val in new_wcs.to_header().items():
header[key] = val
# force WCS for POL60 to have same pixel size as POL0 and POL120 # force WCS for POL60 to have same pixel size as POL0 and POL120
is_pol60 = np.array([head["filtnam1"].lower() == "pol60" for head in headers], dtype=bool) is_pol60 = np.array([head["filtnam1"].lower() == "pol60" for head in headers], dtype=bool)

View File

@@ -154,27 +154,46 @@ def sci_not(v, err, rnd=1, out=str):
return *output[1:], -power return *output[1:], -power
def wcs_PA(PC21, PC22): def wcs_CD_to_PC(CD):
""" """
Return the position angle in degrees to the North direction of a wcs Return the position angle in degrees to the North direction of a wcs
from the values of coefficient of its transformation matrix. from the values of coefficient of its transformation matrix.
---------- ----------
Inputs: Inputs:
PC21 : float CD : np.ndarray
Value of the WCS matric PC[1,0] Value of the WCS matrix CD
PC22 : float ----------
Value of the WCS matric PC[1,1] Returns:
cdelt : (float, float)
Scaling factor in arcsec between pixel in X and Y directions.
orient : float
Angle in degrees between the North direction and the Up direction of the WCS.
"""
det = CD[0, 0] * CD[1, 1] - CD[0, 1] * CD[1, 0]
sgn = -1.0 if det < 0 else 1.0
cdelt = np.array([sgn, 1.0]) * np.sqrt(np.sum(CD**2, axis=1))
rot = np.arctan2(-CD[1, 0], sgn * CD[0, 0])
rot2 = np.arctan2(sgn * CD[0, 1], CD[1, 1])
orient = 0.5 * (rot + rot2) * 180.0 / np.pi
return cdelt, orient
def wcs_PA(PC, cdelt):
"""
Return the position angle in degrees to the North direction of a wcs
from the values of coefficient of its transformation matrix.
----------
Inputs:
PC : np.ndarray
Value of the WCS matrix PC
cdelt : (float, float)
Scaling factor in arcsec between pixel in X and Y directions.
---------- ----------
Returns: Returns:
orient : float orient : float
Angle in degrees between the North direction and the Up direction of the WCS. Angle in degrees between the North direction and the Up direction of the WCS.
""" """
if (abs(PC21) > abs(PC22)) and (PC21 >= 0): rot = np.pi / 2.0 - np.arctan2(-cdelt[1] * PC[1, 0], abs(cdelt[0]) * PC[0, 0])
orient = -np.arccos(PC22) * 180.0 / np.pi rot2 = np.pi / 2.0 - np.arctan2(abs(cdelt[0]) * PC[0, 1], cdelt[1] * PC[1, 1])
elif (abs(PC21) > abs(PC22)) and (PC21 < 0): orient = 0.5 * (rot + rot2) * 180.0 / np.pi
orient = np.arccos(PC22) * 180.0 / np.pi
elif (abs(PC21) < abs(PC22)) and (PC22 >= 0):
orient = np.arccos(PC22) * 180.0 / np.pi
elif (abs(PC21) < abs(PC22)) and (PC22 < 0):
orient = -np.arccos(PC22) * 180.0 / np.pi
return orient return orient