Source code for pynpoint.processing.darkflat
"""
Pipeline modules for dark frame and flat field calibrations.
"""
import time
import warnings
from typing import Tuple
import numpy as np
from typeguard import typechecked
from pynpoint.core.processing import ProcessingModule
from pynpoint.util.module import progress, memory_frames
@typechecked
def _master_frame(data: np.ndarray,
im_shape: Tuple[int, int, int]) -> np.ndarray:
"""
Internal function which creates a master dark/flat by calculating the mean (3D data) and
cropping the frames to the shape of the science images if needed.
Parameters
----------
data : numpy.ndarray
Input array (2D) with mean of the dark or flat frames.
im_shape : tuple(int, int, int)
Shape of the science images (3D).
Returns
-------
numpy.ndarray
Master dark/flat frame.
"""
shape_in = (im_shape[1], im_shape[2])
if data.shape[0] < shape_in[0] or data.shape[1] < shape_in[1]:
raise ValueError('Shape of the calibration images is smaller than the science images.')
if data.shape != shape_in:
cal_shape = data.shape
x_off = (cal_shape[0] - shape_in[0]) // 2
y_off = (cal_shape[1] - shape_in[1]) // 2
data = data[x_off:x_off+shape_in[0], y_off:y_off+shape_in[1]]
warnings.warn('The calibration images were cropped around their center to match the shape '
'of the science images.')
return data
[docs]class DarkCalibrationModule(ProcessingModule):
"""
Pipeline module to subtract a master dark from the science data.
"""
__author__ = 'Markus Bonse, Tomas Stolker'
@typechecked
def __init__(self,
name_in: str,
image_in_tag: str,
dark_in_tag: str,
image_out_tag: str) -> None:
"""
Parameters
----------
name_in : str
Unique name of the module instance.
image_in_tag : str
Tag of the database entry with the science images that are read as input.
dark_in_tag : str
Tag of the database with the dark frames that are read as input.
image_out_tag : str
Tag of the database entry that is written as output.
Returns
-------
NoneType
None
"""
super().__init__(name_in)
self.m_image_in_port = self.add_input_port(image_in_tag)
self.m_dark_in_port = self.add_input_port(dark_in_tag)
self.m_image_out_port = self.add_output_port(image_out_tag)
[docs] @typechecked
def run(self) -> None:
"""
Run method of the module. Creates a master dark with the same shape as the science
data and subtracts the dark frame from the science data.
Returns
-------
NoneType
None
"""
memory = self._m_config_port.get_attribute('MEMORY')
nimages = self.m_image_in_port.get_shape()[0]
frames = memory_frames(memory, nimages)
dark = self.m_dark_in_port.get_all()
master = _master_frame(data=np.mean(dark, axis=0),
im_shape=self.m_image_in_port.get_shape())
start_time = time.time()
for i in range(len(frames[:-1])):
progress(i, len(frames[:-1]), 'Subtracting the dark current...', start_time)
images = self.m_image_in_port[frames[i]:frames[i+1], ]
self.m_image_out_port.append(images - master, data_dim=3)
history = f'dark_in_tag = {self.m_dark_in_port.tag}'
self.m_image_out_port.add_history('DarkCalibrationModule', history)
self.m_image_out_port.copy_attributes(self.m_image_in_port)
self.m_image_out_port.close_port()
[docs]class FlatCalibrationModule(ProcessingModule):
"""
Pipeline module to apply a flat field correction to the science data.
"""
__author__ = 'Markus Bonse, Tomas Stolker'
@typechecked
def __init__(self,
name_in: str,
image_in_tag: str,
flat_in_tag: str,
image_out_tag: str) -> None:
"""
Parameters
----------
name_in : str
Unique name of the module instance.
image_in_tag : str
Tag of the science database that is read as input.
flat_in_tag : str
Tag of the flat field database that is read as input.
image_out_tag : str
Tag of the database entry that is written as output.
Returns
-------
NoneType
None
"""
super().__init__(name_in)
self.m_image_in_port = self.add_input_port(image_in_tag)
self.m_flat_in_port = self.add_input_port(flat_in_tag)
self.m_image_out_port = self.add_output_port(image_out_tag)
[docs] @typechecked
def run(self) -> None:
"""
Run method of the module. Creates a master flat with the same shape as the science
image and divides the science images by the flat field.
Returns
-------
NoneType
None
"""
memory = self._m_config_port.get_attribute('MEMORY')
nimages = self.m_image_in_port.get_shape()[0]
frames = memory_frames(memory, nimages)
flat = self.m_flat_in_port.get_all()
master = _master_frame(data=np.mean(flat, axis=0),
im_shape=self.m_image_in_port.get_shape())
# shift all values to greater or equal to +1.0
flat_min = np.amin(master)
master -= flat_min - 1.
# normalization, median value is 1 afterwards
master /= np.median(master)
start_time = time.time()
for i in range(len(frames[:-1])):
progress(i, len(frames[:-1]), 'Flat fielding the images...', start_time)
images = self.m_image_in_port[frames[i]:frames[i+1], ]
self.m_image_out_port.append(images/master, data_dim=3)
history = f'flat_in_tag = {self.m_flat_in_port.tag}'
self.m_image_out_port.add_history('FlatCalibrationModule', history)
self.m_image_out_port.copy_attributes(self.m_image_in_port)
self.m_image_out_port.close_port()