Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 75 additions & 1 deletion skyreader/plot/plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from matplotlib import patheffects
from matplotlib import pyplot as plt
from matplotlib import text
from matplotlib.path import Path as PolyPath
from matplotlib.projections import projection_registry # type: ignore[import]

from .plotting_tools import (
Expand Down Expand Up @@ -280,6 +281,7 @@ def create_plot_zoomed(
systematics=False,
plot_bounding_box=False,
plot_fermi_sources=False,
check_fermi_sources_box=False,
circular=False,
circular_err50=0.2,
circular_err90=0.7,
Expand Down Expand Up @@ -589,7 +591,10 @@ def bounding_box(ra, dec, theta, phi):
)

if plot_fermi_sources:
sources_in_90 = self._save_sources_inside_90_box(ra, dec, ra_fermi_sources, dec_fermi_sources, name_fermi_sources, rectangular_errors["90"])
if check_fermi_sources_box:
sources_in_90 = self._save_sources_inside_90_box(ra, dec, ra_fermi_sources, dec_fermi_sources, name_fermi_sources, rectangular_errors["90"])
else:
sources_in_90 = self._save_sources_inside_90_contour(ra, dec, ra_fermi_sources, dec_fermi_sources, name_fermi_sources, contours_by_level[1])

if plot_bounding_box:
bounding_ras_list, bounding_decs_list = [], []
Expand Down Expand Up @@ -744,6 +749,32 @@ def bounding_box(ra, dec, theta, phi):
if plot_fermi_sources:
return sources_in_90

def _sources_inside_90_contour(self, ra_src, dec_src, name_src, contours):
# Convert inputs to numpy arrays
name_src = np.asarray(name_src)
ra_src = np.asarray(ra_src, dtype=float) % 360.0
dec_src = np.asarray(dec_src, dtype=float)
# Convert (RA, Dec) → spherical coordinates used by healpy
# theta = colatitude (0 = North pole, pi = South pole)
# phi = longitude
src_theta = np.pi/2 - np.deg2rad(dec_src)
src_phi = np.deg2rad(ra_src)
# Combine coordinates into point array: (theta, phi)
points = np.column_stack([src_theta, src_phi])
# Initialize mask: False for all sources initially
inside_mask = np.zeros(len(points), dtype=bool)
for contour in contours:
# contour is (theta, phi)
contour_theta = contour[:, 0]
contour_phi = contour[:, 1]
# Build polygon in (theta, phi) space
poly = np.column_stack([contour_theta, contour_phi])
# Create a 2D path object for point-in-polygon test
path = PolyPath(poly)
# Update mask: mark sources inside this contour as True
inside_mask |= path.contains_points(points)
return name_src[inside_mask], ra_src[inside_mask], dec_src[inside_mask]

def _sources_inside_90_box(self, ra_best_fit, dec_best_fit, ra_src, dec_src, name_src, rectangular_errors):
ra_min = ra_best_fit + rectangular_errors["ra_minus"]
ra_max = ra_best_fit + rectangular_errors["ra_plus"]
Expand All @@ -765,6 +796,49 @@ def _sources_inside_90_box(self, ra_best_fit, dec_best_fit, ra_src, dec_src, nam
mask = ra_ok & dec_ok
return name_src[mask], ra_src[mask], dec_src[mask]

def _save_sources_inside_90_contour(self, ra_best_fit, dec_best_fit, ra_src, dec_src, name_src, contour):
src_inside_90_name, src_inside_90_ra, src_inside_90_dec = self._sources_inside_90_contour(
ra_src,
dec_src,
name_src,
contour
)
ang_dist = np.zeros(len(src_inside_90_name), dtype=float)
for i in range(len(src_inside_90_name)):
ang_dist[i] = pyasl.getAngDist(
ra_best_fit,
dec_best_fit,
src_inside_90_ra[i],
src_inside_90_dec[i]
)
sources_in_90 = [
{
"name": name,
"ra": ra_src,
"dec": dec_src,
"ang_dist": dist
}
for name, ra_src, dec_src, dist in zip(
src_inside_90_name,
src_inside_90_ra,
src_inside_90_dec,
ang_dist
)
]
sources_in_90_sorted = sorted(
sources_in_90,
key=lambda s: s["ang_dist"]
)
print("\nFermi sources inside 90% contour:\n")
for s in sources_in_90_sorted:
print(
f"- {s['name'].strip()}\n"
f" RA: {s['ra']:.3f} deg\n"
f" Dec: {s['dec']:.3f} deg\n"
f" ang_dist: {s['ang_dist']:.3f} deg\n"
)
return sources_in_90

def _save_sources_inside_90_box(self, ra_best_fit, dec_best_fit, ra_src, dec_src, name_src, rectangular_errors):
src_inside_90_name, src_inside_90_ra, src_inside_90_dec = self._sources_inside_90_box(
ra_best_fit,
Expand Down
Loading