Example #1
0
    def make_custom_lc(
        self,
        sector=None,
        sap_mask=None,
        aper_radius=None,
        percentile=None,
        threshold_sigma=None,
        use_pld=True,
        pixel_components=3,
        spline_n_knots=100,
        spline_degree=3,
        background_mask=None,
        pca_nterms=5,
        with_offset=True,
    ):
        """
        create a custom lightcurve with background subtraction, based on this tutorial:
        https://docs.lightkurve.org/tutorials/04-how-to-remove-tess-scattered-light-using-regressioncorrector.html

        Parameters
        ----------
        sector : int or str
            specific sector or all
        aper_radius: int
            aperture mask radius
        percentile: float
            aperture mask percentile
        threshold_sigma: float
            aperture mask threshold [sigma]
        pca_nterms : int
            number of pca terms to use

        Returns
        -------
        corrected_lc : lightkurve object
        """
        if self.verbose:
            print("Using lightcurve with custom aperture.")
        sector = sector if sector is not None else self.sector
        sap_mask = sap_mask if sap_mask else self.sap_mask
        aper_radius = aper_radius if aper_radius else self.aper_radius
        percentile = percentile if percentile else self.percentile
        threshold_sigma = (threshold_sigma
                           if threshold_sigma else self.threshold_sigma)
        if self.tpf is None:
            tpf, tpf_info = self.get_tpf(sector=sector, return_df=True)
        else:
            if self.tpf.sector == sector:
                tpf = self.tpf
            else:
                tpf, tpf_info = self.get_tpf(sector=sector, return_df=True)
        # Make an aperture mask and a raw light curve
        self.aper_mask = parse_aperture_mask(
            tpf,
            sap_mask=sap_mask,
            aper_radius=aper_radius,
            percentile=percentile,
            threshold_sigma=threshold_sigma,
            verbose=False,
        )
        raw_lc = tpf.to_lightcurve(method="aperture",
                                   aperture_mask=self.aper_mask)
        # remove nans
        idx = (np.isnan(raw_lc.time)
               | np.isnan(raw_lc.flux)
               | np.isnan(raw_lc.flux_err))
        self.tpf = tpf[~idx]
        self.raw_lc = raw_lc[~idx]

        if use_pld:
            if self.verbose:
                print("Removing scattered light + applying PLD")
            pld = lk.TessPLDCorrector(self.tpf, aperture_mask=self.aper_mask)
            if background_mask is None:
                background_mask = ~self.aper_mask
            corrected_lc = pld.correct(
                pixel_components=pixel_components,
                spline_n_knots=spline_n_knots,
                spline_degree=spline_degree,
                background_mask=background_mask,
            )
            self.corrector = pld
        else:
            if self.verbose:
                print("Removing scattered light")
            # Make a design matrix and pass it to a linear regression corrector
            regressors = tpf.flux[~idx][:, ~self.aper_mask]
            dm = (lk.DesignMatrix(
                regressors, name="pixels").pca(pca_nterms).append_constant())

            # Regression Corrector Object
            rc = lk.RegressionCorrector(self.raw_lc)
            self.corrector = rc
            corrected_lc = rc.correct(dm)

            # Optional: Remove the scattered light, allowing for the large offset from scattered light
            if with_offset:
                corrected_lc = (self.raw_lc - rc.model_lc +
                                np.percentile(rc.model_lc.flux, q=5))
        lc = corrected_lc.normalize()
        self.lc_custom = lc
        # compute Contamination
        if self.gaia_sources is None:
            gaia_sources = self.query_gaia_dr2_catalog(radius=120,
                                                       verbose=False)
        else:
            gaia_sources = self.gaia_sources
        fluxes = get_fluxes_within_mask(self.tpf, self.aper_mask, gaia_sources)
        self.contratio = sum(fluxes) - 1
        if self.tic_params is None:
            _ = self.query_tic_catalog(return_nearest_xmatch=True)
        tic_contratio = self.tic_params.contratio
        dcontratio = abs(tic_contratio - self.contratio)
        if (tic_contratio is not None) & (dcontratio > 0.5):
            print(f"contratio: {self.contratio:.2f} (TIC={tic_contratio:.2f})")

        # add method
        lc.detrend = lambda: detrend(lc)
        return lc
Example #2
0
    def make_custom_lc(
        self,
        sector=None,
        tpf_size=None,
        sap_mask=None,
        aper_radius=None,
        percentile=None,
        threshold_sigma=None,
        use_pld=True,
        pixel_components=3,
        spline_n_knots=100,
        spline_degree=3,
        background_mask=None,
        pca_nterms=5,
        with_offset=True,
    ):
        """
        create a custom lightcurve based on this tutorial:
        https://docs.lightkurve.org/tutorials/04-how-to-remove-tess-scattered-light-using-regressioncorrector.html

        Parameters
        ----------
        sector : int or str
            specific sector or all
        cutout_size : tuple
            tpf cutout size
        aper_radius: int
            aperture mask radius
        percentile: float
            aperture mask percentile
        threshold_sigma: float
            aperture mask threshold [sigma]
        method : float
            PLD (default)

        Returns
        -------
        corrected_lc : lightkurve object
        """
        if self.verbose:
            print("Using lightcurve with custom aperture.")
        sector = sector if sector is not None else self.sector
        sap_mask = sap_mask if sap_mask else self.sap_mask
        aper_radius = aper_radius if aper_radius else self.aper_radius
        percentile = percentile if percentile else self.percentile
        threshold_sigma = (threshold_sigma
                           if threshold_sigma else self.threshold_sigma)
        cutout_size = tpf_size if tpf_size else self.cutout_size

        tpf_tesscut = self.get_tpf_tesscut(sector=sector,
                                           cutout_size=cutout_size)

        self.aper_mask = parse_aperture_mask(
            tpf_tesscut,
            sap_mask=sap_mask,
            aper_radius=aper_radius,
            percentile=percentile,
            threshold_sigma=threshold_sigma,
            verbose=False,
        )

        raw_lc = tpf_tesscut.to_lightcurve(method="aperture",
                                           aperture_mask=self.aper_mask)
        # remove nans
        idx = (np.isnan(raw_lc.time)
               | np.isnan(raw_lc.flux)
               | np.isnan(raw_lc.flux_err))
        self.tpf_tesscut = tpf_tesscut[~idx]
        self.lc_custom_raw = raw_lc[~idx]

        if use_pld:
            if self.verbose:
                print("Removing scattered light + applying PLD")
            pld = lk.TessPLDCorrector(self.tpf_tesscut,
                                      aperture_mask=self.aper_mask)
            if background_mask is None:
                background_mask = ~self.aper_mask
            corrected_lc = pld.correct(
                pixel_components=pixel_components,
                spline_n_knots=spline_n_knots,
                spline_degree=spline_degree,
                background_mask=background_mask,
            )
            self.corrector = pld
        else:
            if self.verbose:
                print("Removing scattered light")
            # Make a design matrix and pass it to a linear regression corrector
            regressors = tpf_tesscut.flux[~idx][:, ~self.aper_mask]
            dm = (lk.DesignMatrix(
                regressors,
                name="regressors").pca(nterms=pca_nterms).append_constant())
            rc = lk.RegressionCorrector(raw_lc)
            self.corrector = rc
            corrected_lc = rc.correct(dm)

            # Optional: Remove the scattered light, allowing for the large offset from scattered light
            if with_offset:
                corrected_lc = (raw_lc - rc.model_lc +
                                np.percentile(rc.model_lc.flux, q=5))
        lc = corrected_lc.normalize()
        self.lc_custom = lc

        # compute Contamination
        if self.gaia_sources is None:
            gaia_sources = self.query_gaia_dr2_catalog(radius=120)
        else:
            gaia_sources = self.gaia_sources
        fluxes = get_fluxes_within_mask(self.tpf_tesscut, self.aper_mask,
                                        gaia_sources)
        self.contratio = sum(fluxes) - 1
        # add method
        lc.detrend = lambda: detrend(lc)
        return lc
Example #3
0
 def get_lc(self, lctype="pdcsap", sector=None, quality_bitmask=None):
     """
     """
     sector = sector if sector is not None else self.sector
     quality_bitmask = (quality_bitmask
                        if quality_bitmask else self.quality_bitmask)
     if self.lcf is not None:
         # reload lcf if already in memory
         if self.lcf.sector == sector:
             lcf = self.lcf
         else:
             query_str = (f"TIC {self.ticid}"
                          if self.ticid else self.target_coord)
             if self.verbose:
                 print(
                     f"Searching lightcurvefile for {query_str} (sector {sector})"
                 )
             q = lk.search_lightcurvefile(query_str,
                                          sector=sector,
                                          mission=MISSION)
             if len(q) == 0:
                 if self.verbose:
                     print(
                         f"Searching lightcurvefile for {self.target_coord.to_string()} (sector {sector})"
                     )
                 q = lk.search_lightcurvefile(self.target_coord,
                                              sector=sector,
                                              mission=MISSION)
             assert q is not None, "Empty result. Check long cadence."
             if self.verbose:
                 print(f"Found {len(q)} lightcurves")
             if (sector == "all") & (len(self.all_sectors) > 1):
                 lcf = q.download_all(quality_bitmask=quality_bitmask)
             else:
                 lcf = q.download(quality_bitmask=quality_bitmask)
             self.lcf = lcf
     else:
         query_str = (f"TIC {self.ticid}"
                      if self.ticid else self.target_coord)
         if self.verbose:
             print(
                 f"Searching lightcurvefile for {query_str} (sector {sector})"
             )
         q = lk.search_lightcurvefile(query_str,
                                      sector=sector,
                                      mission=MISSION)
         if len(q) == 0:
             if self.verbose:
                 print(
                     f"Searching lightcurvefile for {self.target_coord.to_string()} (sector {sector})"
                 )
             q = lk.search_lightcurvefile(self.target_coord,
                                          sector=sector,
                                          mission=MISSION)
         assert q is not None, "Empty result. Check long cadence."
         if self.verbose:
             print(f"Found {len(q)} lightcurves")
         if (sector == "all") & (len(self.all_sectors) > 1):
             lcf = q.download_all(quality_bitmask=quality_bitmask)
         else:
             lcf = q.download(quality_bitmask=quality_bitmask)
         self.lcf = lcf
     assert lcf is not None, "Empty result. Check long cadence."
     sap = lcf.SAP_FLUX
     pdcsap = lcf.PDCSAP_FLUX
     if isinstance(lcf, lk.LightCurveFileCollection):
         # merge multi-sector into one lc
         if len(lcf) > 1:
             sap0 = sap[0].normalize()
             sap = [sap0.append(l.normalize()) for l in sap[1:]][0]
             pdcsap0 = pdcsap[0].normalize()
             pdcsap = [pdcsap0.append(l.normalize()) for l in pdcsap[1:]][0]
         else:
             raise ValueError(
                 f"Only sector {lcf[0].sector} (in {self.all_sectors}) is available"
             )
     self.lc_sap = sap
     self.lc_pdcsap = pdcsap
     if lctype == "pdcsap":
         # add detrend method to lc instance
         pdcsap.detrend = lambda: detrend(pdcsap)
         return pdcsap.remove_nans().normalize()
     else:
         sap.detrend = lambda: detrend(sap)
         return sap.remove_nans().normalize()
Example #4
0
 def _get_lc(self, lctype="pdcsap", campaign=None, quality_bitmask=None):
     """
     FIXME: refactor to lightcurve.py?
     """
     campaign = campaign if campaign is not None else self.campaign
     quality_bitmask = (quality_bitmask if quality_bitmask is not None else
                        self.quality_bitmask)
     if self.lcf is not None:
         # reload lcf if already in memory
         if self.lcf.campaign == campaign:
             lcf = self.lcf
         else:
             query_str = (f"EPIC {self.epicid}"
                          if self.epicid else self.target_coord)
             if self.verbose:
                 print(
                     f"Searching lightcurvefile for {query_str} (campaign {campaign})"
                 )
             q = lk.search_lightcurvefile(query_str,
                                          campaign=campaign,
                                          mission="K2")
             if len(q) == 0:
                 if self.verbose:
                     print(
                         f"Searching lightcurvefile for {self.target_coord.to_string()} (campaign {campaign})"
                     )
                 q = lk.search_lightcurvefile(self.target_coord,
                                              campaign=campaign,
                                              mission="K2")
             assert q is not None, "Empty result. Check long cadence."
             if self.verbose:
                 print(f"Found {len(q)} lightcurves")
             if (campaign == "all") & (len(self.all_campaigns) > 1):
                 NotImplementedError
                 # lcf = q.download_all(quality_bitmask=quality_bitmask)
             else:
                 lcf = q.download(quality_bitmask=quality_bitmask)
             self.lcf = lcf
     else:
         query_str = (f"EPIC {self.epicid}"
                      if self.epicid else self.target_coord)
         if self.verbose:
             print(
                 f"Searching lightcurvefile for {query_str} (campaign {campaign})"
             )
         q = lk.search_lightcurvefile(query_str,
                                      campaign=campaign,
                                      mission="K2")
         if len(q) == 0:
             if self.verbose:
                 print(
                     f"Searching lightcurvefile for ra,dec=({self.target_coord.to_string()}) (campaign {campaign})"
                 )
             q = lk.search_lightcurvefile(self.target_coord,
                                          campaign=campaign,
                                          mission="K2")
         assert q is not None, "Empty result. Check long cadence."
         if self.verbose:
             print(f"Found {len(q)} lightcurves")
         if (campaign == "all") & (len(self.all_campaigns) > 1):
             NotImplementedError
             # lcf = q.download_all(quality_bitmask=quality_bitmask)
         else:
             lcf = q.download(quality_bitmask=quality_bitmask)
         self.lcf = lcf
     assert lcf is not None, "Empty result. Check long cadence."
     sap = lcf.SAP_FLUX
     pdcsap = lcf.PDCSAP_FLUX
     if isinstance(lcf, lk.LightCurveFileCollection):
         # merge multi-campaign into one lc
         if len(lcf) > 1:
             sap0 = sap[0].normalize()
             sap = [sap0.append(l.normalize()) for l in sap[1:]][0]
             pdcsap0 = pdcsap[0].normalize()
             pdcsap = [pdcsap0.append(l.normalize()) for l in pdcsap[1:]][0]
         else:
             raise ValueError(
                 f"Only campaign {lcf[0].campaign} (in {self.all_campaigns}) is available"
             )
     self.lc_sap = sap
     self.lc_pdcsap = pdcsap
     if lctype == "pdcsap":
         # add detrend method to lc instance
         pdcsap.detrend = lambda: detrend(pdcsap)
         return pdcsap.remove_nans().normalize()
     else:
         sap.detrend = lambda: detrend(sap)
         return sap.remove_nans().normalize()