Skip to content

Commit

Permalink
plot unwarped sources also
Browse files Browse the repository at this point in the history
  • Loading branch information
scivision committed Feb 6, 2024
1 parent 13174ea commit 9f4c89b
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 40 deletions.
6 changes: 3 additions & 3 deletions scripts/OverlayAltitudes.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from pathlib import Path
from argparse import ArgumentParser

from astrometry_azel.plot import add_image
from astrometry_azel.plot import wcs_image

from matplotlib.pyplot import figure, show

Expand All @@ -37,11 +37,11 @@
if p.subplots:
axs: typing.Any = fg.subplots(1, len(flist), sharey=True, sharex=True)
for fn, ax in zip(flist, axs):
add_image(fn, "gray", ax)
wcs_image(fn, "gray", ax)

else:
ax = fg.gca()
for fn, cm in zip(flist, cmaps):
add_image(fn, cm, ax, alpha=0.05)
wcs_image(fn, cm, ax, alpha=0.05)

show()
103 changes: 69 additions & 34 deletions scripts/OverlayStars.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,64 +4,99 @@
Overlay stars from a catalog on an image.
This is like a closed loop check that solve-field output (here, the .rdls file) makes sense.
Use --tag-all option of solve-field to output star magnitude in the .rdls file:
Procedure starting with a .fits file to solve:
1. Use --tag-all option of solve-field to output star magnitude in the .rdls file:
solve-field src/astrometry_azel/tests/apod4.fits --tag-all
2. Run this script to overlay stars on the image -- warped and unwarped.
python scripts/OverlayStars.py src/astrometry_azel/tests/apod4
"""

import argparse
from pathlib import Path

import numpy as np

from astrometry_azel.io import get_sources
from astrometry_azel.plot import add_image
from astrometry_azel.plot import wcs_image, xy_image

from matplotlib.pyplot import figure, show


def label_stars(ax, x, y, mag_norm=None):
if mag_norm is not None:
ax.scatter(
x,
y,
s=100 * mag_norm,
edgecolors="red",
marker="o",
facecolors="none",
label="stars",
)
else:
ax.scatter(
x,
y,
s=25,
edgecolors="red",
marker="o",
facecolors="none",
label="stars",
)


p = argparse.ArgumentParser()
p.add_argument("rdls_file", help="FITS .rdls filename output from solve-field (Astrometry.net)")
p.add_argument("new_file", help="FITS .new filename output from solve-field (Astrometry.net)")
p.add_argument(
"stem", help="FITS file stem (without .suffix) output from solve-field (Astrometry.net)"
)
p = p.parse_args()

source_ra = get_sources(p.rdls_file)
stem = Path(p.stem)
new = stem.with_suffix(".new")

rdls = stem.with_suffix(".rdls")
source_ra = get_sources(rdls)

fg = figure()
ax = fg.gca()
add_image(p.new_file, "gray", ax)

xyls = stem.parent / (stem.name + "-indx.xyls")
source_xy = get_sources(xyls)

if "MAG" in source_ra.columns.names:
Ntot = source_ra.shape[0]
Nkeep = 20 # only plot the brightest stars
source_ra.sort(axis=0, order="MAG")
source_ra = source_ra[:Nkeep]

i = source_ra.argsort(axis=0, order="MAG")

source_ra = np.take_along_axis(source_ra, i, axis=0)[:Nkeep]
source_xy = np.take_along_axis(source_xy, i, axis=0)[:Nkeep]

# normalize star magnitude to [0,1]
mag_norm = (source_ra["MAG"] - source_ra["MAG"].min()) / np.ptp(source_ra["MAG"])

ax.scatter(
source_ra["RA"],
source_ra["DEC"],
s=100 * mag_norm,
edgecolors="red",
marker="o",
facecolors="none",
label="stars",
)
ttxt = f"{p.rdls_file} {source_ra.shape[0]} / {Ntot} stars on {p.new_file}"
ttxt = f"{stem}: {source_ra.shape[0]} / {Ntot} stars"
else:
ax.scatter(
source_ra["RA"],
source_ra["DEC"],
s=25,
edgecolors="red",
marker="o",
facecolors="none",
label="stars",
)
ttxt = f"{p.rdls_file} {source_ra.shape[0]} stars on {p.new_file}"


ax.set_title(ttxt, wrap=True)
mag_norm = None
ttxt = f"{stem} {source_ra.shape[0]} stars"

# %% unwarped image

fgy = figure()
axy = fgy.gca()
xy_image(new, "gray", axy)

label_stars(axy, source_xy["X"], source_xy["Y"], mag_norm)
axy.set_title(ttxt, wrap=True)

# %% WCS warped image

fgr = figure()
axr = fgr.gca()
wcs_image(new, "gray", axr)

label_stars(axr, source_ra["RA"], source_ra["DEC"], mag_norm)
axr.set_title(ttxt, wrap=True)

show()
29 changes: 26 additions & 3 deletions src/astrometry_azel/plot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,11 +175,12 @@ def image_stack(img, fn: Path, clim=None):
fg.savefig(plotFN)


def add_image(fn: Path, cm, ax, alpha=1):
def wcs_image(fn: Path, cmap, ax, alpha=1):
"""
Astrometry.net makes file ".new" with the image and the WCS SIP 2-D polynomial fit coefficients in the FITS header
We use DECL as "x" and RA as "y".
Warps the image to sky coordinates using the WCS.
pcolormesh() is used as it handles arbitrary pixel shapes.
Note that pcolormesh() cannot tolerate NaN in X or Y (NaN in C is OK).
Expand All @@ -201,6 +202,28 @@ def add_image(fn: Path, cm, ax, alpha=1):
dec = radec[:, 1].reshape((yPix, xPix), order="C")

ax.set_title(fn.name)
ax.pcolormesh(ra, dec, img, alpha=alpha, cmap=cm, norm=LogNorm())
ax.pcolormesh(ra, dec, img, alpha=alpha, cmap=cmap, norm=LogNorm())
ax.set_ylabel("Right Ascension [deg.]")
ax.set_xlabel("Declination [deg.]")


def xy_image(fn: Path, cmap, ax):
"""
Astrometry.net makes file ".new" with the image and the WCS SIP 2-D polynomial fit coefficients in the FITS header
We use DECL as "x" and RA as "y".
pcolormesh() is used as it handles arbitrary pixel shapes.
Note that pcolormesh() cannot tolerate NaN in X or Y (NaN in C is OK).
https://github.com/scivision/python-matlab-examples/blob/main/PlotPcolor/pcolormesh_NaN.py
"""

fn = Path(fn).expanduser().resolve(True)

with fits.open(fn, mode="readonly", memmap=False) as f:
img = f[0].data

ax.set_title(fn.name)
ax.pcolormesh(img, cmap=cmap, norm=LogNorm())
ax.set_ylabel("y - pixel")
ax.set_xlabel("x - pixel")

0 comments on commit 9f4c89b

Please sign in to comment.