def smoother(aperture, pxs, config): smooth = np.zeros_like(pxs, dtype=float) for x, y in utils.positions(smooth): smooth[x, y] = pxs[x, y].intersection(aperture).area return smooth
def pixels(shape, config): pxs = np.empty(shape, dtype=object) for x, y in utils.positions(pxs): pxs[x, y] = shp.geometry.box(x - config.dither, y - config.dither, x + config.dither, y + config.dither) return pxs
def plot_ani(fig, flximg, aperture, config): flxs = flximg["FLUX"] trac = flximg["TRACK"] vmin, vmax = percentile_sample(flxs) ax = fig.add_subplot(111) ax.set_title("Centroid Tracking and Annulus Animation") ax.set_xlim(left=-0.5, right=flxs.shape[1]-0.5) ax.set_ylim(bottom=-0.5, top=flxs.shape[2]-0.5) im = ax.matshow(np.zeros(flxs.shape[1:]), cmap="gray", norm=mpl.colors.LogNorm(vmin=vmin, vmax=vmax), origin="lower", interpolation="none") pl, = ax.plot([], [], "r+", mew=5, ms=40) txt = ax.text(0.05, 0.05, "", fontsize=26, color="w", backgroundcolor="k", transform=ax.transAxes) fill, = ax.plot([], [], "kx", mew=6, ms=50) apxs = np.zeros(flxs.shape[1:], dtype=bool) for x, y in utils.positions(apxs): apxs[x, y] = not aperture.intersection(shp.geometry.box(x, y, x + 1, y + 1)).is_empty pxs = pixels(flxs.shape[1:], dither=dither) def animate(i): if i >= flxs.shape[0]: raise StopIteration flx = flxs[i] x, y = trac[i] + np.array(flx.shape) / 2 apy, apx = (np.array(np.where(apxs)).T - trac[i]).T # Smooth and weight using the aperture. _aperture = shp.affinity.translate(aperture, *-trac[i]) flx *= smoother(_aperture, pxs, config) flx[flx == 0] = np.min(flx[flx != 0]) im.set_array(flx) pl.set_data([x], [y]) #fill.set_data(apx, apy) txt.set_text("Frame #%d" % (i,)) #return [im, pl, fill, txt] return [im, pl, txt] ani = mpl.animation.FuncAnimation(fig, animate, interval=15, frames=flxs.shape[0], blit=True, repeat=False) if config.ofile: ani.save(config.ofile, writer=mpl.animation.writers['ffmpeg'](fps=15, bitrate=5000), dpi=50) else: plt.show()
def main(fits, outf, config): hdulist = astropy.io.fits.open(fits) # Make sure the shape is the same for each frame. chsize = hdulist[1].data.shape assert(hdu.data.shape == chsize for hdu in hdulist[1:]) # Create the FFI and special "0" arrays. ffisize = np.array(CHANNELS.shape) * chsize full = np.zeros(ffisize) # Frames for special modules. null = np.nan * np.ones(chsize) black = np.zeros(chsize) for position in utils.positions(CHANNELS): channel = CHANNELS[position] if channel == NL: frame = null elif channel in BLACKLIST: frame = black else: frame = hdulist[channel].data[::COLS[position],::ROWS[position]] frame = normalize(frame, config) # Set up slices to broadcast to. start = np.array(position) * chsize sl = [slice(s, e) for s, e in zip(start, start + chsize)] full[sl] = frame # Flip vertically to match image origin in top-left. full = full[::-1,...] newhdus = astropy.io.fits.HDUList([ astropy.io.fits.PrimaryHDU(), astropy.io.fits.ImageHDU(data=full), ]) newhdus.writeto(outf, clobber=True)