diff --git a/plotastrodata/fits_utils.py b/plotastrodata/fits_utils.py index ad407b1..9b83c8e 100644 --- a/plotastrodata/fits_utils.py +++ b/plotastrodata/fits_utils.py @@ -130,7 +130,11 @@ def get_center(self) -> str: """ ra_deg = self.get_header('CRVAL1') dec_deg = self.get_header('CRVAL2') - return xy2coord([ra_deg, dec_deg]) + radesys = self.get_header('RADESYS') + a = xy2coord([ra_deg, dec_deg]) + if radesys is not None: + a = f'{radesys} {a}' + return a def gen_data(self, Tb: bool = False, log: bool = False, drop: bool = True, restfreq: float = None) -> None: @@ -180,6 +184,9 @@ def gen_grid(self, center: str | None = None, dist: float = 1., # spatial center if center is not None: c0 = xy2coord([h['CRVAL1'], h['CRVAL2']]) + if 'RADESYS' in h: + radesys = h['RADESYS'] + c0 = f'{radesys} {c0}' cx, cy = coord2xy(center, c0) else: cx, cy = 0, 0 diff --git a/plotastrodata/other_utils.py b/plotastrodata/other_utils.py index ef260ce..a430958 100644 --- a/plotastrodata/other_utils.py +++ b/plotastrodata/other_utils.py @@ -1,7 +1,7 @@ import subprocess import shlex import numpy as np -from astropy.coordinates import SkyCoord +from astropy.coordinates import SkyCoord, FK5, FK4 from astropy import units from scipy.optimize import curve_fit from scipy.special import erf @@ -42,19 +42,92 @@ def listing(*args) -> list: return b -def coord2xy(coords: str, coordorg: str = '00h00m00s 00d00m00s', - frame: str = 'icrs', frameorg: str = 'icrs') -> np.ndarray: +def _getframe(coord: str, s: str = '') -> tuple: + """Internal function to pick up the frame name from the coordinates. + + Args: + coord (str): something like "J2000 01h23m45.6s 01d23m45.6s" + s (str, optional): To distinguish coord and coordorg. Defaults to ''. + + Returns: + tuple: updated coord and frame. frame is FK5(equinox='J2000), FK4(equinox='B1950'), or 'icrs'. + """ + if len(c := coord.split()) == 3: + coord = f'{c[1]} {c[2]}' + if 'J2000' in c[0]: + print(f'J2000 found in coord{s}. FK5(J2000) is used.') + frame = FK5(equinox='J2000') + elif 'FK5' in c[0]: + print(f'FK5 found in coord{s}. FK5(J2000) is used.') + frame = FK5(equinox='J2000') + elif 'B1950' in c[0]: + print(f'B1950 found in coord{s}. FK4(B1950) is used.') + frame = FK4(equinox='B1950') + elif 'FK4' in c[0]: + print(f'FK4 found in coord{s}. FK4(B1950) is used.') + frame = FK4(equinox='B1950') + elif 'ICRS' in c[0]: + frame = 'icrs' + else: + print(f'Unknown equinox found in coord{s}. ICRS is used') + frame = 'icrs' + else: + frame = None + return coord, frame + + +def _updateframe(frame: str) -> str: + """Internal function to str frame to astropy frame. + + Args: + frame (str): _description_ + + Returns: + str: frame as is, FK5(equinox='J2000'), FK4(equinox='B1950'), or 'icrs'. + """ + if 'ICRS' in frame: + a = 'icrs' + elif 'J2000' in frame or 'FK5' in frame: + a = FK5(equinox='J2000') + elif 'B1950' in frame or 'FK4' in frame: + a = FK4(equinox='B1950') + else: + a = frame + return a + + +def coord2xy(coords: str | list, coordorg: str = '00h00m00s 00d00m00s', + frame: str | None = None, frameorg: str | None = None, + ) -> np.ndarray: """Transform R.A.-Dec. to relative (deg, deg). Args: - coords (str): something like '01h23m45.6s 01d23m45.6s'. The input can be a list of str in an arbitrary shape. - coordorg (str): something like '01h23m45.6s 01d23m45.6s'. The origin of the relative (deg, deg). Defaults to '00h00m00s 00d00m00s'. - frame (str): coordinate frame. Defaults to 'icrs'. - frameorg (str): coordinate frame of the origin. Defaults to 'icrs'. + coords (str, list): something like '01h23m45.6s 01d23m45.6s'. The input can be a list of str in an arbitrary shape. + coordorg (str, optional): something like '01h23m45.6s 01d23m45.6s'. The origin of the relative (deg, deg). Defaults to '00h00m00s 00d00m00s'. + frame (str, optional): coordinate frame. Defaults to None. + frameorg (str, optional): coordinate frame of the origin. Defaults to None. Returns: np.ndarray: [(array of) alphas, (array of) deltas] in degree. The shape of alphas and deltas is the input shape. With a single input, the output is [alpha0, delta0]. """ + coordorg, frameorg_c = _getframe(coordorg, 'org') + frameorg = frameorg_c if frameorg is None else _updateframe(frameorg) + if type(coords) is list: + for i in range(len(coords)): + coords[i], frame_c = _getframe(coords[i]) + else: + coords, frame_c = _getframe(coords) + frame = frame_c if frame is None else _updateframe(frame) + if frame is None and frameorg is not None: + frame = frameorg + if frame is not None and frameorg is None: + frameorg = frame + if frame is None and frameorg is None: + frame = frameorg = 'icrs' + if frame != frameorg: + frame = frameorg + print('Different frame and frameorg are not supported by coord2xy yet.', + frameorg, 'is used.') clist = SkyCoord(coords, frame=frame) c0 = SkyCoord(coordorg, frame=frameorg) xy = c0.spherical_offsets_to(clist) @@ -62,18 +135,24 @@ def coord2xy(coords: str, coordorg: str = '00h00m00s 00d00m00s', def xy2coord(xy: list, coordorg: str = '00h00m00s 00d00m00s', - frame: str = 'icrs', frameorg: str = 'icrs') -> str: + frame: str | None = None, frameorg: str | None = None, + ) -> str: """Transform relative (deg, deg) to R.A.-Dec. Args: xy (list): [(array of) alphas, (array of) deltas] in degree. alphas and deltas can have an arbitrary shape. coordorg (str): something like '01h23m45.6s 01d23m45.6s'. The origin of the relative (deg, deg). Defaults to '00h00m00s 00d00m00s'. - frame (str): coordinate frame. Defaults to 'icrs'. - frameorg (str): coordinate frame of the origin. Defaults to 'icrs'. + frame (str): coordinate frame. Defaults to None. + frameorg (str): coordinate frame of the origin. Defaults to None. Returns: str: something like '01h23m45.6s 01d23m45.6s'. With multiple inputs, the output has the input shape. """ + coordorg, frameorg_c = _getframe(coordorg, 'org') + frameorg = frameorg_c if frameorg is None else _updateframe(frameorg) + if frameorg is None: + frameorg = 'icrs' + frame = frameorg if frame is None else _updateframe(frame) c0 = SkyCoord(coordorg, frame=frameorg) coords = c0.spherical_offsets_by(*xy * units.degree) coords = coords.transform_to(frame=frame) diff --git a/plotastrodata/plot_utils.py b/plotastrodata/plot_utils.py index 68fe6e2..6209baf 100644 --- a/plotastrodata/plot_utils.py +++ b/plotastrodata/plot_utils.py @@ -935,6 +935,9 @@ def set_axis_radec(self, center: str | None = None, center = self.center if center is None: center = '00h00m00s 00d00m00s' + if len(csplit := center.split()) == 3: + center = f'{csplit[1]} {csplit[2]}' + print(center) dec = np.radians(coord2xy(center)[1]) def get_sec(x, i): diff --git a/testFITS/test2D.fits b/testFITS/test2D.fits index 6147608..cb0ba4c 100644 Binary files a/testFITS/test2D.fits and b/testFITS/test2D.fits differ diff --git a/testFITS/test2D_2.fits b/testFITS/test2D_2.fits index 3cda2ec..eecc4ba 100644 Binary files a/testFITS/test2D_2.fits and b/testFITS/test2D_2.fits differ diff --git a/testFITS/test2Damp.fits b/testFITS/test2Damp.fits index 48c6028..0e4315d 100644 Binary files a/testFITS/test2Damp.fits and b/testFITS/test2Damp.fits differ diff --git a/testFITS/test2Dang.fits b/testFITS/test2Dang.fits index 2bf91e6..0086a3d 100644 Binary files a/testFITS/test2Dang.fits and b/testFITS/test2Dang.fits differ diff --git a/testFITS/test3D.fits b/testFITS/test3D.fits index b299564..5e8620c 100644 Binary files a/testFITS/test3D.fits and b/testFITS/test3D.fits differ diff --git a/testFITS/testB.fits b/testFITS/testB.fits index 8c5c568..2cb8bf3 100644 Binary files a/testFITS/testB.fits and b/testFITS/testB.fits differ diff --git a/testFITS/testG.fits b/testFITS/testG.fits index f6661c8..2afd45a 100644 Binary files a/testFITS/testG.fits and b/testFITS/testG.fits differ diff --git a/testFITS/testR.fits b/testFITS/testR.fits index 71e3783..8409a01 100644 Binary files a/testFITS/testR.fits and b/testFITS/testR.fits differ