Move the processing code under pipeline/
Preparing to merge this repository into a combined astrophotography repo. session-scripts/ becomes pipeline/ because the scripts import layout.py from their own directory and must stay together, and because 'pipeline' says what it is rather than how it came about. observing/ stays at the top level: observing plans are not processing code.
This commit is contained in:
parent
653ca103cd
commit
c6299f41ab
53 changed files with 0 additions and 0 deletions
74
pipeline/verify_core.py
Normal file
74
pipeline/verify_core.py
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
"""Is the nucleus of NGC 5128 actually saturated, or was that a foreground star?
|
||||
|
||||
The earlier claim - that the core clips at 65313 ADU in a single 300 s sub -
|
||||
came from taking the maximum inside a 300x300 px box centred on the frame. That
|
||||
box is wide enough to contain a bright foreground star, so the measurement
|
||||
proves only that SOMETHING in the middle of the frame is bright. This checks
|
||||
where the bright pixels actually are, and what the galaxy itself peaks at once
|
||||
stars are filtered out.
|
||||
"""
|
||||
import numpy as np
|
||||
from astropy import units as u
|
||||
from astropy.coordinates import SkyCoord
|
||||
from astropy.io import fits
|
||||
from astropy.wcs import WCS
|
||||
from scipy.ndimage import median_filter
|
||||
|
||||
import layout
|
||||
|
||||
SUB = layout.path("calibrated-T32-qisback-NGC5128-20260721-190133"
|
||||
"-Luminance-BIN2-W-300-002.fit")
|
||||
MASTER = layout.path("master-Luminance.fit")
|
||||
|
||||
# NGC 5128's nucleus, from SIMBAD, not from "the middle of the frame".
|
||||
NUCLEUS = SkyCoord("13h25m27.6s", "-43d01m08.8s")
|
||||
|
||||
with fits.open(MASTER) as hd:
|
||||
wcs = WCS(hd[0].header, naxis=2)
|
||||
nx_c, ny_c = wcs.world_to_pixel(NUCLEUS)
|
||||
print(f"nucleus lands at master pixel ({nx_c:.1f}, {ny_c:.1f})")
|
||||
|
||||
data = fits.getdata(SUB).astype(np.float32)
|
||||
ny, nx = data.shape
|
||||
print(f"single sub {nx} x {ny}, global max {data.max():.0f} ADU")
|
||||
|
||||
# Where are the saturated-ish pixels?
|
||||
ys, xs = np.where(data > 60000)
|
||||
print(f"{len(xs)} pixels above 60000 ADU")
|
||||
if len(xs):
|
||||
# Cluster them crudely by proximity to see how many distinct objects.
|
||||
print(f" x range {xs.min()}-{xs.max()}, y range {ys.min()}-{ys.max()}")
|
||||
cx, cy = nx / 2.0, ny / 2.0
|
||||
d = np.hypot(xs - cx, ys - cy)
|
||||
print(f" distance from frame centre: min {d.min():.0f} px, "
|
||||
f"median {np.median(d):.0f} px, max {d.max():.0f} px")
|
||||
# The brightest pixel specifically
|
||||
iy, ix = np.unravel_index(np.argmax(data), data.shape)
|
||||
print(f" brightest pixel at ({ix}, {iy}), "
|
||||
f"{np.hypot(ix - cx, iy - cy):.0f} px from frame centre")
|
||||
|
||||
# The galaxy's own peak: median filter removes stars, which are small, while
|
||||
# leaving the smooth galaxy light essentially untouched.
|
||||
h = 400
|
||||
y0, y1 = int(ny / 2) - h, int(ny / 2) + h
|
||||
x0, x1 = int(nx / 2) - h, int(nx / 2) + h
|
||||
core = data[y0:y1, x0:x1]
|
||||
smooth = median_filter(core, size=15)
|
||||
print(f"\ninner {2*h}x{2*h} px box:")
|
||||
print(f" raw max {core.max():9.1f} ADU")
|
||||
print(f" median-filtered max {smooth.max():9.1f} ADU <- galaxy light")
|
||||
iy, ix = np.unravel_index(np.argmax(smooth), smooth.shape)
|
||||
print(f" galaxy peak at frame pixel ({x0+ix}, {y0+iy})")
|
||||
|
||||
# How many pixels of the median-filtered (star-free) galaxy are near clipping?
|
||||
for lvl in (30000, 50000, 60000):
|
||||
print(f" star-free pixels above {lvl}: {(smooth > lvl).sum()}")
|
||||
|
||||
# And in the master stack.
|
||||
mdata = fits.getdata(MASTER).astype(np.float32)
|
||||
mcore = mdata[y0:y1, x0:x1]
|
||||
msmooth = median_filter(mcore, size=15)
|
||||
print(f"\nmaster stack inner box: raw max {mcore.max():.1f}, "
|
||||
f"star-free max {msmooth.max():.1f} ADU")
|
||||
print(f" master 99.995th percentile (the stretch white point) "
|
||||
f"{np.percentile(mdata, 99.995):.1f} ADU")
|
||||
Loading…
Add table
Add a link
Reference in a new issue