Two catalogues were created from the same field where one set of data included dithering at two levels, $3\mathrm{"}$ and $30\mathrm{"}$. The other data set included no dithering. These files are contained in catalogue-matching/topcat-match.fits.
In [278]:
import fitsio
from astropy.coordinates import ICRS
from astropy import units as u
from scipy import stats
from pyslalib import slalib
rc('lines', markersize=2)
In [279]:
def analyse_hdu(hdu):
data = hdu['RA', 'DEC', 'RAJ2000', 'DEJ2000'].read()
test_point = ICRS(ra=data['RA'], dec=data['DEC'], unit=(u.radian, u.radian))
ref_point = ICRS(ra=data['RAJ2000'], dec=data['DEJ2000'], unit=(u.degree, u.degree))
separations = ref_point.separation(test_point)
return separations.arcsecond
In [280]:
fname = 'catalogue-matching/topcat-match.fits'
with fitsio.FITS(fname) as infile:
dithered_hdu = infile['dithered_match']
normal_hdu = infile['normal_match']
dithered_separations = analyse_hdu(dithered_hdu)
normal_separations = analyse_hdu(normal_hdu)
In [281]:
plt.hist([dithered_separations, normal_separations], 30, label=['Dithered', 'Normal'],
histtype='step')
plt.legend(loc='best')
plt.xlabel(r'Separation / arcseconds')
Out[281]:
We can see that overall the dithered data show smaller separations, but the tail is still quite long. What is the source for this long tail? We shall plot a few things:
In [282]:
with fitsio.FITS(fname) as infile:
jmag = infile['dithered_match']['Jmag'].read()
In [283]:
rms = lambda values: np.std(values) / float(values.size)
In [284]:
plt.plot(jmag, dithered_separations, 'k.')
plt.gca().invert_xaxis()
plt.xlabel(r'J magnitude')
plt.ylabel(r'Separation')
med_magnitudes, ledge, _ = stats.binned_statistic(jmag, dithered_separations, statistic='median', bins=20)
errs, _, _ = stats.binned_statistic(jmag, dithered_separations, statistic=rms, bins=ledge)
# plt.errorbar(ledge[:-1] + np.diff(ledge)[0] / 2., med_magnitudes, errs, ls='None', color='r')
plt.plot(ledge[:-1], med_magnitudes, 'r-', drawstyle='steps-post')
Out[284]:
So we can see from this that for this case the areas with highest RMS separation are above $\sim J = 8$ and towards the fainter magnitudes. This is not unexpected as brighter than $J=8$ the stars are saturated in NGTS data, and at fainter magnitudes the stars have more uncertainty in their pixel positions.
Pixel phase can be computed from position % 1 to get the fractional position in each coordinate. If higher uncertainties are nearer pixel edges we should see a distribution which is high or low towards 0 and 1, and the opposite in between.
In [285]:
with fitsio.FITS(fname) as infile:
data = infile['dithered_match']['X_coordinate', 'Y_coordinate'].read()
x, y = map(np.array, zip(*[(row['X_coordinate'], row['Y_coordinate']) for row in data]))
x_phase = x % 1
y_phase = y % 1
In [290]:
def display_phase_separations(axis, phase, separations):
med, ledges, _ = stats.binned_statistic(phase, separations, statistic='median', bins=15)
errs, _, _ = stats.binned_statistic(phase, separations, statistic=rms, bins=ledges)
ydata = np.hstack([med, [med[-1]]])
edata = np.hstack([errs, [errs[-1]]])
bin_centres = ledges + np.diff(ledges)[0] / 2.
# Plotting
axis[0].plot(phase, separations, 'k.', alpha=0.2)
axis[1].plot(ledges, ydata, 'r-', drawstyle='steps-post')
# axis[1].errorbar(bin_centres, ydata, edata, ls='None', color='r')
fig, axes = plt.subplots(2, 2)
for (axis, phase) in zip(axes, [x_phase, y_phase]):
display_phase_separations(axis, phase, dithered_separations)
At a push there is a slight decrease in accuracy when stars are very near a pixel edge (at separation == 0). This is not visible in the raw data (left) but is apparent when binning.
We already have the x and y coordinates for each matched star, we can display the separations in the third dimension somehow.
In [288]:
plt.scatter(x, y, c=dithered_separations, edgecolor='None', cmap='afmhot')
plt.colorbar()
Out[288]:
This display is not too useful, instead compute the median separation in bins.
In [289]:
stat, xedges, yedges, _ = stats.binned_statistic_2d(x, y, dithered_separations,
statistic='median',
bins=32)
m_stat = ma.masked_where(stat != stat, stat)
plt.pcolormesh(xedges[:-1], yedges[:-1], m_stat, cmap='afmhot')
plt.colorbar()
plt.axis(aspect='equal', xlim=(0, 2048), ylim=(0, 2048))
plt.xlim(0, 2048)
plt.ylim(0, 2048)
Out[289]:
There does seem to be a spatial dependence, at least it's not uniform. It does not seem to be worse in the corners particularly, just at the centre there is a bright spot towards the top right of the centre, and a dark spot at the lower left.
As there seems to be no systematic dependence on chip position, there is probably no dependence on altitude. This would show up in a change in declination.
In [306]:
with fitsio.FITS(fname) as infile:
dec = np.degrees(infile['dithered_match']['DEC'].read())
plt.plot(dec, dithered_separations, 'k.', alpha=0.3)
binned, ledges, _ = stats.binned_statistic(dec, dithered_separations, statistic='median', bins=30)
plt.plot(ledges[:-1], binned, 'r-', drawstyle='steps-post')
Out[306]: