Пример #1
0
    def _combine_calib_images(
        images: List[Image], bias: Optional[Image] = None, normalize: bool = False, method: str = "average"
    ) -> Image:
        """Combine a list of given images.

        Args:
            images: List of images to combine.
            bias: If given, subtract from images before combining them.
            normalize: If True, images are normalized to median of 1 before and after combining them.
            method: Method for combining images.
        """
        import ccdproc

        # get CCDData objects
        data = [image.to_ccddata() for image in images]

        # subtract bias?
        if bias is not None:
            bias_data = bias.to_ccddata()
            data = [ccdproc.subtract_bias(d, bias_data) for d in data]

        # normalize?
        if normalize:
            data = [d.divide(np.median(d.data), handle_meta="first_found") for d in data]

        # combine image
        combined = ccdproc.combine(
            data,
            method=method,
            sigma_clip=True,
            sigma_clip_low_thresh=5,
            sigma_clip_high_thresh=5,
            mem_limit=350e6,
            unit="adu",
            combine_uncertainty_function=np.ma.std,
        )

        # normalize?
        if normalize:
            combined = combined.divide(np.median(combined.data), handle_meta="first_found")

        # to Image and copy header
        image = Image.from_ccddata(combined)

        # add history
        for i, src in enumerate(images, 1):
            basename = src.header["FNAME"].replace(".fits.fz", "").replace(".fits", "")
            image.header["L1AVG%03d" % i] = (basename, "Image used for average")
        image.header["RLEVEL"] = (1, "Reduction level")

        # finished
        return image
Пример #2
0
    async def __call__(self, image: Image) -> Image:
        """Calibrate an image.

        Args:
            image: Image to calibrate.

        Returns:
            Calibrated image.
        """
        import ccdproc

        # get calibration masters
        try:
            bias = await self._find_master(image, ImageType.BIAS)
            dark = await self._find_master(image, ImageType.DARK)
            flat = await self._find_master(image, ImageType.SKYFLAT)
        except ValueError as e:
            log.error("Could not find calibration frames: " + str(e))
            return image

        # calibrate image
        c = await asyncio.get_running_loop().run_in_executor(
            None,
            partial(
                ccdproc.ccd_process,
                image.to_ccddata(),
                oscan=image.header["BIASSEC"]
                if "BIASSEC" in image.header else None,
                trim=image.header["TRIMSEC"]
                if "TRIMSEC" in image.header else None,
                error=True,
                master_bias=bias.to_ccddata() if bias is not None else None,
                dark_frame=dark.to_ccddata() if dark is not None else None,
                master_flat=flat.to_ccddata() if flat is not None else None,
                bad_pixel_mask=None,
                gain=image.header["DET-GAIN"] * u.electron / u.adu,
                readnoise=image.header["DET-RON"] * u.electron,
                dark_exposure=dark.header["EXPTIME"] *
                u.second if dark is not None else None,
                data_exposure=image.header["EXPTIME"] * u.second,
                dark_scale=True,
                gain_corrected=False,
            ),
        )

        # to image
        calibrated = Image.from_ccddata(c)
        calibrated.header["BUNIT"] = ("electron", "Unit of pixel values")

        # set raw filename
        if "ORIGNAME" in image.header:
            calibrated.header["L1RAW"] = image.header["ORIGNAME"].replace(
                ".fits", "")

        # add calibration frames
        if bias is not None:
            calibrated.header["L1BIAS"] = (
                bias.header["FNAME"].replace(".fits.fz",
                                             "").replace(".fits", ""),
                "Name of BIAS frame",
            )
        if dark is not None:
            calibrated.header["L1DARK"] = (
                dark.header["FNAME"].replace(".fits.fz",
                                             "").replace(".fits", ""),
                "Name of DARK frame",
            )
        if flat is not None:
            calibrated.header["L1FLAT"] = (
                flat.header["FNAME"].replace(".fits.fz",
                                             "").replace(".fits", ""),
                "Name of FLAT frame",
            )

        # set RLEVEL
        calibrated.header["RLEVEL"] = (1, "Reduction level")

        # finished
        return calibrated