You can use lightkurve
to extract a lightcurve of transient phenomena, including supernovae. Supernovae data analysis presents a few unique challenges compared to data analysis of isolated point sources. We can anticipate some of the common limitations of the Kepler pipeline-processed lightcurves, which make no attempt to hone-in on supernovae. For example, the supernova resides in a host galaxy which may itself be time variable due to, e.g., active galactic nuclei (AGN). Common detrending methods, such as "Self Flat Fielding" (SFF) assume that centroid shifts are due entirely to undesired motion of the spacecraft, while transients induce bona-fide astrophysical centroid motion as the postage-stamp photocenter gets weighted towards the increasingly luminous transient's photocenter.
In this tutorial we will custom-make a custom supernova lightcurve with these simple steps:
We will focus on an unusual class of transient recently observed in K2, the so-called Fast-Evolving Luminous Transients or FELTs. These transients rise and fall within a mere few days, much shorter than conventional supernovae, which can last hundreds of days. The discovery of KSN2015k was recently reported by Rest et al. 2018 and summarized in at least two press releases from STSci and JPL.
The EPIC ID for KSN2015k
's host galaxy is 212593538.
%matplotlib inline
import numpy as np
from lightkurve import search_targetpixelfile
tpf = search_targetpixelfile('EPIC 212593538', campaign=6).download()
tpf.shape
(3561, 8, 8)
The TPF has 3561 useable cadences, with an $8 \times 8$ postage stamp image.
tpf.plot(frame=100);
The coarse angular resolution of Kepler means that this host galaxy resembles a pixelated blob. We're showing frame 100 out of 3561 frames-- we do not presently know when the supernova went off so it's hard to say whether there is a supernova in the image or not.
One of the pixels is white, which represents NaN
values in the color image. In fact, this pixel within the $8 \times 8$ square postage stamp image boundary is NaN
in all 3561 cadences, indicating that this TPF has an irregular boundary with $N_{\rm pix} = 63$. Irregular boundaries are a common space-saving strategy for the distant Kepler telescope.
postage_stamp_mask = tpf.hdu[2].data > 0
postage_stamp_mask.sum()
63
Let's make a lightcurve summing all of the pixels to see if we can pick out the FELT by-eye. We will pre-process the lightcurve to remove sharp discontinuities in the time series that arise from spurious cosmic rays, not our astrophysical transient of interest.
lc_raw = tpf.to_lightcurve(aperture_mask='all')
_, spurious_cadences = lc_raw.flatten().remove_outliers(return_mask=True)
lc_clean = lc_raw[~spurious_cadences]
lc_clean.errorbar(alpha=0.5, normalize=False);
Voilà! We indeed see what looks like a sharply-rising phenomenon at $t = 2400-2415$ days, distinct from the smoothly-varying background, which could arise from either instrumental artifacts or host-galaxy.
Let's identify where the FELT was located within the host galaxy and its K2 postage stamp. We can either visually inspect the lightcurve with interact to look for the position of the explosion, or we can programmatically select cadences to estimate a difference image. I used interact
with a fine-tuned screen-stretch to see that the FELT appears near pixel column 830, row 231. Furthermore, it looks like the flux drops off significantly in the first and last columns.
#tpf.interact(lc=lc_clean)
Once we have our aperture and background masks, we can estimate the net flux $f_{\rm net}$ as:
$f_{\rm net}(t) = f_{\rm aper}(t) - f_{\rm b}(t) \cdot N_{\rm aper}$
where $f_{\rm aper}$ is the total summed flux in an aperture of size $N_{\rm aper}$ pixels, and $f_{b}$ is our estimate for the (spatially-flat) background level per pixel, in each cadence.
aperture_mask = postage_stamp_mask.copy()
aperture_mask[:,-1] = False
aperture_mask[:,0] = False
background_mask = ~aperture_mask & postage_stamp_mask
N_targ_pixels, N_back_pixels = aperture_mask.sum(), background_mask.sum()
N_targ_pixels, N_back_pixels
(48, 15)
tpf.plot(aperture_mask=aperture_mask);
tpf.plot(aperture_mask=background_mask);
Checks out. Let's apply the equation above:
lc_aper = tpf.to_lightcurve(aperture_mask=aperture_mask)
lc_back_per_pixel = tpf.to_lightcurve(aperture_mask=background_mask) / N_back_pixels
lc_net = lc_aper - lc_back_per_pixel.flux * N_targ_pixels
Drop the previously-identified spurious cadences.
lc_net = lc_net[~spurious_cadences]
lc_net.errorbar();
Much better! We no longer see the instrumentally-induced background wiggles.
I can see lots of spacecraft motion jittering the postage stamp image back-and-forth, a common instrumental artifact in K2 data. Let's attempt to mitigate the spacecraft motion with the SFF algorithm, knowing that it might delete some of the astrophysical signal of interest.
lc_corr = lc_net.to_corrector(method='sff')
ax = lc_net.errorbar(color='red', alpha=0.5, label='With Motion')
ax = lc_corr.lc.errorbar(ax=ax, color='blue', alpha=0.5, label='Motion Corrected');
The SFF method appears to do virtually nothing at all! There are probably two primary reasons-- Our large aperture has captured all of the FELT + host galaxy flux, so the jitter motion has been subdued to the point where SFF has little or no constraining power. A second effect is that large extended objects compensate for flux loss with equal parts of flux gain: flux from the right of the boundary enters when flux from the left exits. This effect subdues the common jig-saw pattern attributable to flux overflowing the pixel mask.
It's conceivable---and likely--- that fine tuning the SFF parameters and pixel mask size would result in a higher signal-to-noise ratio lightcurve. We are presently accepting lots of variance for the purpose of limiting bias.