pyhrs:docs

Source code for pyhrs.hrsprocess

# Licensed under a 3-clause BSD style license - see LICENSE.rst
# This module implements the base processing for HRS data
from __future__ import (absolute_import, division, print_function,
                        unicode_literals)

import os
import numpy as np
from astropy.extern import six

from astropy import units as u

import ccdproc

__all__ = ['ccd_process', 'create_masterbias', 'hrs_process', 'blue_process',
           'red_process']


[docs]def ccd_process(ccd, oscan=None, trim=None, error=False, masterbias=None, bad_pixel_mask=None, gain=None, rdnoise=None, oscan_median=True, oscan_model=None): """Perform basic processing on ccd data. The following steps can be included: * overscan correction * trimming of the image * create edeviation frame * gain correction * add a mask to the data * subtraction of master bias The task returns a processed `ccdproc.CCDData` object. Parameters ---------- ccd: `ccdproc.CCDData` Frame to be reduced oscan: None, str, or, `~ccdproc.ccddata.CCDData` For no overscan correction, set to None. Otherwise proivde a region of `ccd` from which the overscan is extracted, using the FITS conventions for index order and index start, or a slice from `ccd` that contains the overscan. trim: None or str For no trim correction, set to None. Otherwise proivde a region of `ccd` from which the image should be trimmed, using the FITS conventions for index order and index start. error: boolean If True, create an uncertainty array for ccd masterbias: None, `~numpy.ndarray`, or `~ccdproc.CCDData` A materbias frame to be subtracted from ccd. bad_pixel_mask: None or `~numpy.ndarray` A bad pixel mask for the data. The bad pixel mask should be in given such that bad pixels havea value of 1 and good pixels a value of 0. gain: None or `~astropy.Quantity` Gain value to multiple the image by to convert to electrons rdnoise: None or `~astropy.Quantity` Read noise for the observations. The read noise should be in `~astropy.units.electron` oscan_median : bool, optional If true, takes the median of each line. Otherwise, uses the mean oscan_model : `~astropy.modeling.Model`, optional Model to fit to the data. If None, returns the values calculated by the median or the mean. Returns ------- ccd: `ccdproc.CCDData` Reduded ccd Examples -------- 1. To overscan, trim, and gain correct a data set: >>> import numpy as np >>> from astropy import units as u >>> from hrsprocess import ccd_process >>> ccd = CCDData(np.ones([100, 100]), unit=u.adu) >>> nccd = ccd_process(ccd, oscan='[1:10,1:100]', trim='[10:100, 1,100]', error=False, gain=2.0*u.electron/u.adu) """ # make a copy of the object nccd = ccd.copy() # apply the overscan correction if isinstance(oscan, ccdproc.CCDData): nccd = ccdproc.subtract_overscan(nccd, overscan=oscan, median=oscan_median, model=oscan_model) elif isinstance(oscan, six.string_types): nccd = ccdproc.subtract_overscan(nccd, fits_section=oscan, median=oscan_median, model=oscan_model) elif oscan is None: pass else: raise TypeError('oscan is not None, a string, or CCDData object') # apply the trim correction if isinstance(trim, six.string_types): nccd = ccdproc.trim_image(nccd, fits_section=trim) elif trim is None: pass else: raise TypeError('trim is not None or a string') # create the error frame if error and gain is not None and rdnoise is not None: nccd = ccdproc.create_deviation(nccd, gain=gain, rdnoise=rdnoise) elif error and (gain is None or rdnoise is None): raise ValueError( 'gain and rdnoise must be specified to create error frame') # apply the bad pixel mask if isinstance(bad_pixel_mask, np.ndarray): nccd.mask = bad_pixel_mask elif bad_pixel_mask is None: pass else: raise TypeError('bad_pixel_mask is not None or numpy.ndarray') # apply the gain correction if isinstance(gain, u.quantity.Quantity): nccd = ccdproc.gain_correct(nccd, gain) elif gain is None: pass else: raise TypeError('gain is not None or astropy.Quantity') # test subtracting the master bias if isinstance(masterbias, ccdproc.CCDData): nccd = nccd.subtract(masterbias) elif isinstance(masterbias, np.ndarray): nccd.data = nccd.data - masterbias elif masterbias is None: pass else: raise TypeError( 'masterbias is not None, numpy.ndarray, or a CCDData object') return nccd
[docs]def hrs_process(image_name, ampsec=[], oscansec=[], trimsec=[], masterbias=None, error=False, bad_pixel_mask=None, flip=False, rdnoise=None, oscan_median=True, oscan_model=None): """Processing required for HRS observations. If the images have multiple amps, then this will process each part of the image and recombine them into for the final results Parameters ---------- image_name: str Name of file to be processed ampsec: list List of ampsections. This list should have the same length as the number of amps in the data set. The sections should be given in the format of fits_sections (see below). oscansec: list List of overscan sections. This list should have the same length as the number of amps in the data set. The sections should be given in the format of fits_sections (see below). trimsec: list List of overscan sections. This list should have the same length as the number of amps in the data set. The sections should be given in the format of fits_sections (see below). error: boolean If True, create an uncertainty array for ccd masterbias: None, `~numpy.ndarray`, or `~ccdproc.CCDData` A materbias frame to be subtracted from ccd. bad_pixel_mask: None or `~numpy.ndarray` A bad pixel mask for the data. The bad pixel mask should be in given such that bad pixels havea value of 1 and good pixels a value of 0. flip: boolean If True, the image will be flipped such that the orders run from the bottom of the image to the top and the dispersion runs from the left to the right. rdnoise: None or `~astropy.Quantity` Read noise for the observations. The read noise should be in `~astropy.units.electron` oscan_median : bool, optional If true, takes the median of each line. Otherwise, uses the mean oscan_model : `~astropy.modeling.Model`, optional Model to fit to the data. If None, returns the values calculated by the median or the mean. Returns ------- ccd: `~ccdproc.CCDData` Data processed and Notes ----- The format of the `fits_section` string follow the rules for slices that are consistent with the FITS standard (v3) and IRAF usage of keywords like TRIMSEC and BIASSEC. Its indexes are one-based, instead of the python-standard zero-based, and the first index is the one that increases most rapidly as you move through the array in memory order, opposite the python ordering. The 'fits_section' argument is provided as a convenience for those who are processing files that contain TRIMSEC and BIASSEC. The preferred, more pythonic, way of specifying the overscan is to do it by indexing the data array directly with the `overscan` argument. """ # read in the data ccd = ccdproc.CCDData.read(image_name, unit=u.adu) try: namps = ccd.header['CCDAMPS'] except KeyError: namps = ccd.header['CCDNAMPS'] # thow errors for the wrong number of amps if len(ampsec) != namps: raise ValueError('Number of ampsec does not equal number of amps') if len(oscansec) != namps: raise ValueError('Number of oscansec does not equal number of amps') if len(trimsec) != namps: raise ValueError('Number of trimsec does not equal number of amps') if namps == 1: gain = float(ccd.header['gain'].split()[0]) * u.electron / u.adu nccd = ccd_process(ccd, oscan=oscansec[0], trim=trimsec[0], error=error, masterbias=masterbias, bad_pixel_mask=bad_pixel_mask, gain=gain, rdnoise=rdnoise, oscan_median=oscan_median, oscan_model=oscan_model) else: ccd_list = [] xsize = 0 for i in range(namps): cc = ccdproc.trim_image(ccd, fits_section=ampsec[i]) gain = float(ccd.header['gain'].split()[i]) * u.electron / u.adu ncc = ccd_process(cc, oscan=oscansec[i], trim=trimsec[i], error=False, masterbias=None, gain=gain, bad_pixel_mask=None, rdnoise=rdnoise, oscan_median=oscan_median, oscan_model=oscan_model) xsize = xsize + ncc.shape[1] ysize = ncc.shape[0] ccd_list.append(ncc) # now recombine the processed data ncc = ccd_list[0] data = np.zeros((ysize, xsize)) if ncc.mask is not None: mask = np.zeros((ysize, xsize)) else: mask = None if ncc.uncertainty is not None: raise NotImplementedError( 'Support for uncertainties not implimented yet') else: uncertainty = None x1 = 0 for i in range(namps): x2 = x1 + ccd_list[i].data.shape[1] data[:, x1:x2] = ccd_list[i].data if mask is not None: mask[:, x1:x2] = ccd_list[i].mask x1 = x2 nccd = ccdproc.CCDData(data, unit=ncc.unit, mask=mask, uncertainty=uncertainty) nccd = ccd_process(nccd, masterbias=masterbias, error=error, gain=None, rdnoise=rdnoise, bad_pixel_mask=bad_pixel_mask) if flip: nccd.data = nccd.data[::-1, ::-1] if (nccd.mask is not None): nccd.mask = nccd.mask[::-1, ::-1] if (nccd.uncertainty is not None): raise NotImplementedError( 'Flipping is not implimented yet for uncertainty') return nccd
[docs]def blue_process(infile, masterbias=None, error=False, rdnoise=None): """Process a blue frame """ # check to make sure it is a blue file # reduce file blueamp = ['[1:1050,:]', '[1051:2100,:]'] bluescan = ['[1:26,:]', '[1025:1050,:]'] bluetrim = ['[27:1050,:]', '[1:1024,:]'] ccd = hrs_process(infile, ampsec=blueamp, oscansec=bluescan, trimsec=bluetrim, masterbias=masterbias, error=error, rdnoise=None, flip=True) return ccd
[docs]def red_process(infile, masterbias=None, error=None, rdnoise=None): """Process a blue frame """ redamp = ['[1:4122,1:4112]'] redscan = ['[1:25,1:4112]'] redtrim = ['[27:4122,1:4112]'] ccd = hrs_process(infile, ampsec=redamp, oscansec=redscan, trimsec=redtrim, masterbias=masterbias, error=error, rdnoise=None, flip=False) return ccd
def create_masterbias(image_list): """Create a master bias frame from a list of images Parameters ---------- image_list: list List contain the file names to be processed Returns ------- masterbias: ccddata.CCDData Combine master bias from the biases supplied in image_list """ # determine whether they are red or blue if os.path.basename(image_list[0]).startswith('H'): func = blue_process elif os.path.basename(image_list[0]).startswith('R'): func = red_process else: raise TypeError('These are not standard HRS frames') # reduce the files ccd_list = [] for image_name in image_list: ccd = func(image_name, masterbias=None, error=False) ccd_list.append(ccd) # combine the files cb = ccdproc.Combiner(ccd_list) nccd = cb.median_combine(median_func=np.median) return nccd

Page Contents