예제 #1
0
def bkg_subtraction(time, flux, scope="tpf", sigma=3):
    """Subtracts background flux from target pixel file.

    Parameters
    ----------
    scope : string, "tpf" or "postcard"
        If `tpf`, will use data from the target pixel file only to estimate and remove the background.
        If `postcard`, will use data from the entire postcard region to estimate and remove the background.
    sigma : float
        The standard deviation cut used to determine which pixels are representative of the background in each cadence.
    """

    tpf_flux_bkg = []

    sigma_clip = SigmaClip(sigma=sigma)
    #    bkg = MMMBackground(sigma_clip=sigma_clip)
    bkg = SExtractorBackground(sigma_clip=sigma_clip)

    for i in range(len(time)):
        bkg_value = bkg.calc_background(flux[i])
        tpf_flux_bkg.append(bkg_value)

    tpf_flux_bkg = np.array(tpf_flux_bkg)

    return tpf_flux_bkg
예제 #2
0
    def __init__(self, gid, field, flter, nearby_fitting_region, nearby_gids = None):

        if not (field == 'S' or field == 'N'):
            raise Exception('Field must be S or N.')
            
        if not type(flter) == str:
            raise Exception('Filter must be string.')

        self.gid = gid
        self.field = field
        self.flter = flter
        self.nearby_fitting_region = nearby_fitting_region

        if self.flter == '850':
            if self.field == 'N':
                self.fitsfile = 'GOODS-N_acsz_sci_sub.fits'
                self.fullfield = 'North'

            if self.field == 'S':
                self.fitsfile = 'goodss_3dhst.v4.0.F850LP_orig_sci.fits'
                self.fullfield = 'South'
                
        else:
            
            if self.field =='S':
                self.fitsfile = 'goodss_3dhst.v4.0.F'+flter+'W_orig_sci.fits'
                self.fullfield = 'South'

            if self.field =='N':
                self.fitsfile = 'goodsn_3dhst.v4.0.F'+flter+'W_orig_sci.fits'
                self.fullfield = 'North'

        ### CATALOG ###
        if (field == 'S') or (field == 'South'):
            catalog = '/Users/rosaliaobrien/research/website/catalogs/goodss_3dhst.v4.4.cat'
            
        if (field == 'N') or (field == 'North'):
            catalog = '/Users/rosaliaobrien/research/website/catalogs/goodsn_3dhst.v4.4.cat'

        self.cat = ascii.read(catalog)

        ### GET SKY ESTIMATE ###
        if not nearby_gids == None:
            xmin, xmax, ymin, ymax = self.get_boundaries(nearby_gids)
            path = '/Users/rosaliaobrien/research/GALFIT_CLEAR/running_GALFIT/'+self.fullfield+'/'+self.flter+'/'
            skydata = fits.open(path+self.fitsfile)[0].data
            xmid = (xmin+xmax)/2
            ymid = (ymin+ymax)/2
            cutout = Cutout2D(skydata, (xmid, ymid), (400, 400), copy=True, mode='partial')
            masked_cutout = make_source_mask(cutout.data, snr = 1.5,
                            npixels=10, dilate_size=11)
            cutout.data[masked_cutout] = np.nan
            self.scidata = cutout.data
            sigma_clip = SigmaClip(sigma=3)
            bkg = SExtractorBackground(sigma_clip)
            rms = MADStdBackgroundRMS(sigma_clip)
            self.sky_value = bkg.calc_background(cutout.data)
            self.rms_value = rms.calc_background_rms(cutout.data)
예제 #3
0
    def write_intro(self, gids, outputfile, sigma_image, use_mask = False):

        use_mask = True

        # print('Use mask?', use_mask, gid)

        # print(gid)
        
        outputfilefits = outputfile+'.fits'
        
        # if use_mask == False:
        xmin, xmax, ymin, ymax = self.get_boundaries(gids)
        
        # zeropoints taken from https://iopscience.iop.org/article/10.1088/0067-0049/214/2/24/pdf
            
        if self.flter == '850':
            if self.field == 'N':
                inputpsf = 'goodsn_3dhst.v4.0.F850LP_psf.fits'
                psffine = 'none'
                zeropoint_og = 24.871

            if self.field == 'S':
                zeropoint_og = 24.871
                inputpsf = 'goodss_3dhst.v4.0.F850LP_psf.fits'
                psffine = 'none'
                
        elif self.flter == '105':
            if self.field =='S':
                zeropoint_og = 23.972
                inputpsf = 'none'
                psffine = 'none'
                
        else:
            
            if self.flter == '160':
                zeropoint_og = 25.946
                
            if self.flter == '125':
                zeropoint_og = 26.230
                
            if self.flter == '606':
                zeropoint_og = 26.511
                
            if self.flter == '775':
                zeropoint_og = 25.671
            
            if self.field =='S':
                inputpsf = 'goodss_3dhst.v4.0.F'+self.flter+'W_psf.fits'
                psffine = 'goodss_3dhst.v4.0.F'+self.flter+'W_orig_wht.fits'

            if self.field =='N':
                inputpsf = 'goodsn_3dhst.v4.0.F'+self.flter+'W_psf.fits'
                psffine = 'goodsn_3dhst.v4.0.F'+self.flter+'W_orig_wht.fits'
                
        if use_mask == True:

            # print('Using mask!', gid)

            segmap = str(self.gid)+'_segm.fits'
            # if os.path.exists('/Users/rosaliaobrien/research/GALFIT_CLEAR/running_GALFIT/segm_maps/'+segmap) == False:
            print('Creating segmentation map...')
            self.make_segm()

            # Move segmentation map to working directory
            os.rename('/Users/rosaliaobrien/research/GALFIT_CLEAR/running_GALFIT/segm_maps/'+segmap, segmap)

        elif use_mask == False:

            # print('Not using mask!', gid)
            segmap = 'none'
        
        zeropoint=zeropoint_og
        
        if sigma_image == None:
            
            sigma_image = 'none'
            
        
        text = '''================================================================================\n\
    # IMAGE and GALFIT CONTROL PARAMETERS\n\
    A) {0}           # Input data image (FITS file)\n\
    B) {1}     					  # Output data image block\n\
    C) {9}              					  # Sigma image name (made from data if blank or "none") \n\
    D) {2}       # Input PSF image and (optional) diffusion kernel\n
    E) none                                   # PSF fine sampling factor relative to data\n 
    F) {10}              					  # Bad pixel mask (FITS image or ASCII coord list)\n\
    G) none               					  # File with parameter constraints (ASCII file) \n\
    H) {4} {5} {6} {7}       # Image region to fit (xmin xmax ymin ymax)\n\
    I) 200    200        					  # Size of the convolution box (x y)\n\
    J) {8}            					  # Magnitude photometric zeropoint \n\
    K) 0.06  0.06      					  # Plate scale (dx dy)   [arcsec per pixel]\n\
    O) regular           					  # Display type (regular, curses, both)\n\
    P) 0                 					  # Options: 0=normal run; 1,2=make model/imgblock & quit
    \n
    '''.format(self.fitsfile, outputfilefits, inputpsf, psffine, xmin, xmax, ymin, ymax, zeropoint, sigma_image, segmap)

        path = '/Users/rosaliaobrien/research/GALFIT_CLEAR/running_GALFIT/'+self.fullfield+'/'+self.flter+'/'
        skydata = fits.open(path+self.fitsfile)[0].data
        xmid = (xmin+xmax)/2
        ymid = (ymin+ymax)/2
        cutout = Cutout2D(skydata, (xmid, ymid), (400, 400), copy=True, mode='partial')
        masked_cutout = make_source_mask(cutout.data, snr = 1.5,
                        npixels=10, dilate_size=11)
        cutout.data[masked_cutout] = np.nan
        self.scidata = cutout.data
        sigma_clip = SigmaClip(sigma=3)
        bkg = SExtractorBackground(sigma_clip)
        rms = MADStdBackgroundRMS(sigma_clip)
        self.sky_value = bkg.calc_background(cutout.data)
        self.rms_value = rms.calc_background_rms(cutout.data)

        ###PLOT MASKED IMAGE AND SEGMENTATION MAP###
        if use_mask == False: #Plot 1 subplot if not using segmentation map
            num_plots_x = 1
            num_plots_y = 1
        else:
            num_plots_x = 2
            num_plots_y = 1
        fig, ax = plt.subplots(num_plots_y, num_plots_x, figsize = (5,2))
        ax_og = ax #Make 'original' axis in case you splot segmentation map
        if use_mask == True: 
            ax = ax[0]
        im = ax.imshow(self.scidata, vmin = -100, vmax = 100)
        plt.colorbar(im, ax = ax)
        ax.set_title('gid: {}\nSky: {:.2f}\nRMS: {:.2f}'.format(self.gid, self.sky_value, self.rms_value), size=9)
        ax.set_xticklabels([])
        ax.set_yticklabels([])
        if use_mask == False:
            plt.show()
        ########################

        if use_mask == True:
            ax = ax_og
            ### PLOT SEGMAP ###
            segmdata = fits.open(segmap)[0].data
            xmid = (xmin+xmax)/2
            ymid = (ymin+ymax)/2
            cutout = Cutout2D(segmdata, (xmid, ymid), (400, 400), copy=True, mode='partial')

            ax[1].imshow(cutout.data)
            ax[1].set_title('segmentation map'.format(self.gid, self.sky_value, self.rms_value), size=9)
            ax[1].set_xticklabels([])
            ax[1].set_yticklabels([])
            plt.show()
            ########################
            
        return text
예제 #4
0
def make_lc(tic, ra=None, dec=None, process=None):
    print('Calculando Camara y CCD')
    _, _, _, _, cam, ccd, _, _, _ = ts2p(0, ra, dec, trySector=args.Sector)

    idx = (cam[0] - 1) * 4 + (ccd[0] - 1)

    print('Leyendo Header')
    h5 = h5s[idx]
    q = h5['data'][3] == 0
    ffi = np.array(
        glob.glob('/raid/TESS/FFI/s%04d/tess*-s%04d-%d-%d-*ffic.fits' %
                  (args.Sector, args.Sector, cam, ccd)))[q][0]
    hdr = fits.getheader(ffi, 1)

    w = WCS(hdr)
    x, y = w.all_world2pix(ra, dec, 0)

    print('Leyendo hdf5')
    allhdus = FFICut(h5, y, x, args.size)
    hdus = allhdus.hdu

    qual = hdus[1].data['QUALITY'] == 0
    time = hdus[1].data['TIME'][q]
    flux = hdus[1].data['FLUX'][q]
    errs = hdus[1].data['FLUX_ERR'][q]
    bkgs = np.zeros(len(flux))

    print('Calculando Background')
    for i, f in enumerate(flux):
        sigma_clip = SigmaClip(sigma=1)
        bkg = SExtractorBackground(sigma_clip=sigma_clip)
        bkgs[i] = bkg.calc_background(f)

    #DBSCAN Aperture
    x = x - int(x) + args.size // 2
    y = y - int(y) + args.size // 2

    if not args.circ:
        daps = [
            generate_aperture(flux - bkgs[:, None, None], n=i)
            for i in [1, 2, 3, 4, 5]
        ]
        dap = np.array([select_aperture(d, x, y) for d in daps])
    else:
        XX, YY = np.ogrid[:args.size, :args.size]
        dap = [
            np.sqrt((XX - y)**2 + (YY - x)**2) < i
            for i in np.arange(1, 3.1, 0.5)
        ]

    #Aperture photometry
    lcfl = np.einsum('ijk,ljk->li', flux - bkgs[:, None, None], dap)
    lcer = np.sqrt(np.einsum('ijk,ljk->li', np.square(errs), dap))

    #Lightkurves
    lkf = [
        TessLightCurve(time=time, flux=lcfl[i], flux_err=lcer[i])
        for i in range(len(lcfl))
    ]

    #Select best
    cdpp = [lk.estimate_cdpp() for lk in lkf]
    bidx = np.argmin(cdpp)
    lkf = lkf[bidx]

    #Save light curve
    inst = np.repeat('TESS', len(time))
    output = np.transpose([time, lkf.flux, lkf.flux_err, inst])

    np.savetxt('TIC%s.dat' % tic, output, fmt='%s')
    print('LC READY!')

    #Save JPG preview
    stamp = flux - bkgs[:, None, None]
    fig, ax = plt.subplots(figsize=[4, 4])
    fig.patch.set_visible(False)
    stamp = np.log10(np.nanmedian(stamp[::10], axis=0))
    stamp[np.isnan(stamp)] = np.nanmedian(stamp)

    ax.matshow(stamp, cmap='gist_gray', aspect='equal')

    xm, ym = pixel_border(dap[bidx])
    for xi, yi in zip(xm, ym):
        ax.plot(xi, yi, color='lime', lw=1.25)

    ax.plot(x, y, '.r')
    plt.axis('off')
    fig.subplots_adjust(left=0, right=1, top=1, bottom=0, wspace=0, hspace=0)
    fig.savefig('img/TIC%s.png' % tic, dpi=72)

    plt.close(fig)
    del (fig, ax)

    return 1
예제 #5
0
        x, y = w.all_world2pix(ra[i], dec[i], 0)

        allhdus = FFICut(h5, y, x, args.size)
        hdus = allhdus.hdu

        qual = hdus[1].data['QUALITY'] == 0
        time = hdus[1].data['TIME'][q]
        flux = hdus[1].data['FLUX'][q]
        errs = hdus[1].data['FLUX_ERR'][q]
        bkgs = np.zeros(len(flux))

        #print('Calculando Background')
        for i, f in enumerate(flux):
            sigma_clip = SigmaClip(sigma=1)
            bkg = SExtractorBackground(sigma_clip=sigma_clip)
            bkgs[i] = bkg.calc_background(f)

        #DBSCAN Aperture
        x = x - int(x) + flux.shape[1] // 2
        y = y - int(y) + flux.shape[2] // 2

        if not args.circ:
            daps = [
                generate_aperture(flux - bkgs[:, None, None], n=i)
                for i in [1, 2, 3, 4, 5]
            ]
            dap = np.array([select_aperture(d, x, y) for d in daps])
        else:
            XX, YY = np.ogrid[:flux.shape[1], :flux.shape[2]]
            dap = [
                np.sqrt((XX - y)**2 + (YY - x)**2) < i
예제 #6
0
# -*- coding: utf-8 -*-
"""
Created on Fri Oct 11 15:36:33 2019

@author: dingxu
"""
from astropy.io import fits
from astropy.stats import SigmaClip
from photutils import SExtractorBackground

fitsname = 'NGC%2011.fts'
routename1 = 'E:\\shunbianyuan\\ldf_download\\20190921\\'

fitsname1 = routename1+fitsname

hduA1 = fits.open(fitsname1)
imagedataA1 = hduA1[0].data

sigma_clip = SigmaClip(sigma = 3.0)
bkg = SExtractorBackground(sigma_clip)
bkg_value = bkg.calc_background(imagedataA1)

print(bkg_value)
예제 #7
0

#Background and data
ma   = hdus[1].data['QUALITY'] == 0
time = hdus[1].data['TIME'][ma]
flux = hdus[1].data['FLUX'][ma]
errs = hdus[1].data['FLUX_ERR'][ma]
bkgs = np.zeros(len(flux))
berr = np.zeros(len(flux))

#Constant background, bks != 0
if not args.backdrop:
    for i,f in enumerate(flux):
        sigma_clip = SigmaClip(sigma=1)
        bkg        = SExtractorBackground(sigma_clip=sigma_clip)
        bkgs[i]    = bkg.calc_background(f) if args.manualap is None else bkg.calc_background(f[~theap])
        mad_bkg    = mad_std(f)
        berr[i]    = (3*1.253 - 2)*mad_bkg/np.sqrt(f.size)

#Manual aperture
if args.manualap is not None:
    apix2, apix1        = np.genfromtxt(args.manualap, unpack=True).astype(int)
    theap               = np.zeros(flux[0].shape).astype(bool)
    theap[apix1, apix2] = True




#PRF from lightkurve
#if args.prf:
#    print(type(hdus))
예제 #8
0
def GetData(TIC,
            indir,
            outdir,
            cadence='lc',
            S=None,
            fits=None,
            aperture_name=None,
            max_pixels=75,
            saturation_tolerance=-0.1,
            bad_bits=[
                1, 2, 4, 8, 16, 32, 64, 128, 136, 160, 164, 168, 176, 180, 256,
                512, 1024, 2048
            ],
            **kwargs):
    if S is None:
        raise Exception
    sector = ast.literal_eval(S)
    tpf = os.path.join(indir, fits)
    with pyfits.open(tpf) as f:
        qdata = f[1].data
        tpf_aperture = None
        tpf_big_aperture = None,
    apertures = {'tpf': tpf_aperture, 'tpf_big': tpf_big_aperture}
    fitsheader = [
        pyfits.getheader(tpf, 0).cards,
        pyfits.getheader(tpf, 1).cards,
        pyfits.getheader(tpf, 2).cards
    ]
    cadn = np.array(qdata.field('CADENCENO'), dtype='int32')
    time = np.array(qdata.field('TIME'), dtype='float64')
    fpix = np.array(qdata.field('FLUX'), dtype='float64')
    fpix_err = np.array(qdata.field('FLUX_ERR'), dtype='float64')
    qual = np.array(qdata.field('QUALITY'), dtype=int)
    naninds = np.where(np.isnan(time))
    time = Interpolate(np.arange(0, len(time)), naninds, time)
    pc1 = np.array(qdata.field('POS_CORR1'), dtype='float64')
    pc2 = np.array(qdata.field('POS_CORR2'), dtype='float64')
    if not np.all(np.isnan(pc1)) and not np.all(np.isnan(pc2)):
        pc1 = Interpolate(time, np.where(np.isnan(pc1)), pc1)
        pc2 = Interpolate(time, np.where(np.isnan(pc2)), pc2)
    else:
        pc1 = None
        pc2 = None
    f97 = np.zeros((fpix.shape[1], fpix.shape[2]))
    for i in range(fpix.shape[1]):
        for j in range(fpix.shape[2]):
            tmp = np.delete(fpix[:, i, j], np.where(np.isnan(fpix[:, i, j])))
            if len(tmp):
                f = SavGol(tmp)
                med = np.nanmedian(f)
                MAD = 1.4826 * np.nanmedian(np.abs(f - med))
                bad = np.where((f > med + 10. * MAD)
                               | (f < med - 10. * MAD))[0]
                np.delete(tmp, bad)
                i97 = int(0.975 * len(tmp))
                tmp = tmp[np.argsort(tmp)[i97]]
                f97[i, j] = tmp
    sav_ap_name = kwargs.get('sav_aper_name', 'aperture')
    Nmax = np.copy(max_pixels)
    co = 0
    while Nmax >= max_pixels:
        ticmag = fitsheader[0]['TESSMAG'][1]
        if ticmag > 6.5:
            ss = 1.5
        elif 6.5 >= ticmag > 9.:
            ss = 1.3
        elif 9. >= ticmag > 12.:
            ss = 1.2
        elif ticmag < 12.:
            ss = 1.1
        aperture, Nmax = A3d(fpix, N_pixels_max=max_pixels - 1, sigma=ss)
        if np.sum(aperture) == 0.0:
            sys.exit("WARNING: Aperture can't be created, try another TIC")
        elif np.sum(aperture) == 1.0:
            ii = np.where(aperture == 1.)
            try:
                aperture[ii[0] + 1, ii[1]] = 1.
            except:
                pass
            try:
                aperture[ii[0] - 1, ii[1]] = 1.
            except:
                pass
            try:
                aperture[ii[0], ii[1] + 1] = 1.
            except:
                pass
            try:
                aperture[ii[0], ii[1] - 1] = 1.
            except:
                pass
        if fpix.shape[1] < 12 and fpix.shape[2] < 12: break
        if Nmax >= max_pixels:
            nanind = np.where(np.isnan(fpix_err) == 1)
            fpix_err[nanind] = 0.
            bin_row = int(np.ceil(fpix.shape[1] / 12.))
            res_row = fpix.shape[1] % bin_row
            if res_row != 0:
                add_row = bin_row - res_row
                fpix_row = np.ndarray(shape=(fpix.shape[0],
                                             fpix.shape[1] + add_row,
                                             fpix.shape[2]))
                fpix_err_row = np.ndarray(shape=(fpix.shape[0],
                                                 fpix.shape[1] + add_row,
                                                 fpix.shape[2]))
                for fi, fp in enumerate(fpix):
                    SexBkg = SExtractorBackground()
                    fp[fp <= 0.] = 0.0
                    try:
                        fp_bkg = np.ones(
                            fpix.shape[2]) * SexBkg.calc_background(fp)
                    except:
                        fp_bkg = np.zeros(fpix.shape[2])
                    for ad in np.arange(add_row):
                        fp = np.vstack((fp, fp_bkg))
                    fpix_row[fi] = fp
                for fi, fe in enumerate(fpix_err):
                    for ad in np.arange(add_row):
                        fe = np.vstack((fe, np.zeros(fpix_err.shape[2])))
                    fpix_err_row[fi] = fe
                fpix = np.copy(fpix_row)
                fpix_err = np.copy(fpix_err_row)
            bin_col = int(np.ceil(fpix.shape[2] / 12.))
            res_col = fpix.shape[2] % bin_col
            if res_col != 0:
                add_col = bin_col - res_col
                fpix_col = np.ndarray(shape=(fpix.shape[0], fpix.shape[1],
                                             fpix.shape[2] + add_col))
                fpix_err_col = np.ndarray(shape=(fpix.shape[0], fpix.shape[1],
                                                 fpix.shape[2] + add_col))
                for fi, fp in enumerate(fpix):
                    SexBkg = SExtractorBackground()
                    fp[fp <= 0.] = 0.0
                    try:
                        fp_bkg = np.ones(
                            fpix.shape[1]) * SexBkg.calc_background(fp)
                    except:
                        fp_bkg = np.zeros(fpix.shape[1])
                    fp_bkg = fp_bkg.reshape(fp_bkg.shape[0], 1)
                    for ad in np.arange(add_col):
                        fp = np.hstack((fp, fp_bkg))
                    fpix_col[fi] = fp
                for fi, fe in enumerate(fpix_err):
                    for ad in np.arange(add_col):
                        fe = np.hstack(
                            (fe, np.zeros(shape=(fpix.shape[1], 1))))
                fpix = np.copy(fpix_col)
                fpix_err = np.copy(fpix_err_col)
            fpix_bin = np.ndarray(shape=(fpix.shape[0],
                                         fpix[i].shape[0] // bin_row,
                                         fpix[i].shape[1] // bin_col))
            for i, f in enumerate(fpix_bin):
                fpix_bin[i] = fpix[i].reshape(fpix[i].shape[0] // bin_row,
                                              bin_row,
                                              fpix[i].shape[1] // bin_col,
                                              bin_col).sum(3).sum(1)
            fpix = np.copy(fpix_bin)
            fpix_err_bin = np.ndarray(shape=(fpix_err.shape[0],
                                             fpix_err[0].shape[0] // bin_row,
                                             fpix_err[0].shape[1] // bin_col))
            for i, f in enumerate(fpix_err_bin):
                fpix_err_bin[i] = fpix_err[i].reshape(
                    fpix_err[i].shape[0] // bin_row, bin_row,
                    fpix_err[i].shape[1] // bin_col, bin_col).sum(3).sum(1)
            fpix_err = np.copy(fpix_err_bin)
        co += 1
    apertures.update({'automatic': aperture})
    pixel_images = [fpix[0], fpix[len(fpix) // 2], fpix[len(fpix) - 1]]
    if np.sum(aperture) > max_pixels:
        keys = list(apertures.keys())
        npix = np.array([np.sum(apertures[k]) for k in keys])
        aperture_name = keys[np.argmax(npix * (npix <= max_pixels))]
        aperture = apertures[aperture_name]
        aperture[np.isnan(fpix[0])] = 0
        if np.sum(aperture) > max_pixels:
            raise Exception(
                'No apertures available with fewer than {} pixels. Aborting...'
                .format(max_pixels))
    aperture[np.isnan(fpix[0])] = 0
    ap = np.where(aperture == 1)
    fpix2D = np.array([f[ap] for f in fpix], dtype='float64')
    fpix_err2D = np.array([p[ap] for p in fpix_err], dtype='float64')
    binds = np.where(aperture != 1)
    if len(binds[0]) > 0 and sector not in [9, 10, 11]:
        bkg = np.nanmedian(np.array([f[binds] for f in fpix], dtype='float64'),
                           axis=1)
        bkg_err = 1.253 * np.nanmedian(np.array([e[binds] for e in fpix_err],
                                                dtype='float64'),
                                       axis=1) / np.sqrt(len(binds[0]))
        bkg = bkg.reshape(-1, 1)
        bkg_err = bkg_err.reshape(-1, 1)
    elif len(binds[0]) > 0 and sector in [9, 10, 11]:
        bkg = np.zeros_like(fpix2D)
        bkg_err = np.zeros_like(fpix2D)
    else:
        bkg = np.zeros_like(fpix2D)
        bkg_err = np.zeros_like(fpix2D)
    fpix = fpix2D - bkg
    fpix_err = np.sqrt(fpix_err2D**2 + bkg_err**2)
    flux = np.sum(fpix, axis=1)
    ferr = np.sqrt(np.sum(fpix_err**2, axis=1))
    nanmask = np.where(np.isnan(flux) | (flux == 0))[0]
    badmask = []
    for b in bad_bits:
        badmask += list(np.where(qual == b)[0])
    tmpmask = np.array(list(set(np.concatenate([badmask, nanmask]))))
    t = np.delete(time, tmpmask)
    f = np.delete(flux, tmpmask)
    f = SavGol(f)
    med = np.nanmedian(f)
    MAD = 1.4826 * np.nanmedian(np.abs(f - med))
    bad = np.where((f > med + 10. * MAD) | (f < med - 10. * MAD))[0]
    outmask = [np.argmax(time == t[i]) for i in bad]
    fpix = Interpolate(time, nanmask, fpix)
    fpix_err = Interpolate(time, nanmask, fpix_err)
    data = dict(ID=TIC,
                sector=sector,
                cadn=cadn,
                time=time,
                fpix=fpix,
                fpix_err=fpix_err,
                nanmask=np.sort(nanmask),
                badmask=np.sort(badmask),
                outmask=np.sort(outmask),
                aperture=aperture,
                apertures=apertures,
                pixel_images=pixel_images,
                bkg=bkg,
                qual=qual,
                pc1=pc1,
                pc2=pc2,
                fitsheader=fitsheader,
                tessmag=fitsheader[0]['TESSMAG'][1],
                radius=fitsheader[0]['RADIUS'][1],
                ra=fitsheader[0]['RA_OBJ'][1],
                dec=fitsheader[0]['DEC_OBJ'][1],
                pmra=fitsheader[0]['PMRA'][1],
                pmdec=fitsheader[0]['PMDEC'][1],
                teff=fitsheader[0]['TEFF'][1],
                pmtotal=fitsheader[0]['PMTOTAL'][1],
                logg=fitsheader[0]['LOGG'][1],
                feh=fitsheader[0]['MH'][1])
    return data