Skip to content
Chip.py 52.1 KiB
Newer Older
Fang Yuedong's avatar
Fang Yuedong committed
import galsim
import os
import numpy as np
Fang Yuedong's avatar
Fang Yuedong committed
import pickle
import json
import ObservationSim.Instrument._util as _util
Fang Yuedong's avatar
Fang Yuedong committed
from astropy.table import Table
from numpy.random import Generator, PCG64
Fang Yuedong's avatar
Fang Yuedong committed
from astropy.io import fits
from datetime import datetime
Fang Yuedong's avatar
Fang Yuedong committed

from ObservationSim.Instrument.Chip import Effects as effects
from ObservationSim.Instrument.FocalPlane import FocalPlane
from ObservationSim.Config.Header import generatePrimaryHeader, generateExtensionHeader
Fang Yuedong's avatar
Fang Yuedong committed
from ObservationSim.Instrument._util import rotate_conterclockwise
from ObservationSim.Instrument.Chip import ChipUtils as chip_utils
from ObservationSim.Instrument.Chip.libCTI.CTI_modeling import CTI_sim

try:
    import importlib.resources as pkg_resources
except ImportError:
    # Try backported to PY<37 'importlib_resources'
    import importlib_resources as pkg_resources

Fang Yuedong's avatar
Fang Yuedong committed

Fang Yuedong's avatar
Fang Yuedong committed
class Chip(FocalPlane):
    def __init__(self, chipID, ccdEffCurve_dir=None, CRdata_dir=None, sls_dir=None, config=None, treering_func=None, logger=None):
Fang Yuedong's avatar
Fang Yuedong committed
        # Get focal plane (instance of paraent class) info
        super().__init__()
Fang Yuedong's avatar
Fang Yuedong committed
        self.gain_channel = np.ones(self.nsecy * self.nsecx)
Fang Yuedong's avatar
Fang Yuedong committed
        self._set_attributes_from_config(config)
Fang Yuedong's avatar
Fang Yuedong committed

Fang Yuedong's avatar
Fang Yuedong committed
        # A chip ID must be assigned
        self.chipID = int(chipID)
Fang Yuedong's avatar
Fang Yuedong committed
        self.chip_name = str(chipID).rjust(2, '0')
Fang Yuedong's avatar
Fang Yuedong committed

        # Get corresponding filter info
        self.filter_id, self.filter_type = self.getChipFilter()
        self.survey_type = self._getSurveyType()

Fang Yuedong's avatar
Fang Yuedong committed
        if self.filter_type != "FGS":
            self._getChipRowCol()

        # Set the relavent specs for detectors
Fang Yuedong's avatar
Fang Yuedong committed
        try:
            with pkg_resources.files('ObservationSim.Instrument.data.ccd').joinpath("chip_definition.json") as chip_definition:
                with open(chip_definition, "r") as f:
                    chip_dict = json.load(f)[str(self.chipID)]
        except AttributeError:
            with pkg_resources.path('ObservationSim.Instrument.data.ccd', "chip_definition.json") as chip_definition:
                with open(chip_definition, "r") as f:
                    chip_dict = json.load(f)[str(self.chipID)]
        for key in chip_dict:
            setattr(self, key, chip_dict[key])
Fang Yuedong's avatar
Fang Yuedong committed

        self.fdModel = None
Fang Yuedong's avatar
Fang Yuedong committed
        if self.filter_type == "FGS":
            fgs_name = self.chip_name[0:4]
            try:
Fang Yuedong's avatar
Fang Yuedong committed
                with pkg_resources.files('ObservationSim.Instrument.data.field_distortion').joinpath("FieldDistModelGlobal_pr4_%s.pickle" % (fgs_name.lower())) as field_distortion:
                    with open(field_distortion, "rb") as f:
                        self.fdModel = pickle.load(f)
            except AttributeError:
Fang Yuedong's avatar
Fang Yuedong committed
                with pkg_resources.path('ObservationSim.Instrument.data.field_distortion', "FieldDistModelGlobal_pr4_%s.pickle" % (fgs_name.lower())) as field_distortion:
                    with open(field_distortion, "rb") as f:
                        self.fdModel = pickle.load(f)
Fang Yuedong's avatar
Fang Yuedong committed
        else:
            # Get the corresponding field distortion model
            try:
                with pkg_resources.files('ObservationSim.Instrument.data.field_distortion').joinpath("FieldDistModel_v2.0.pickle") as field_distortion:
                    with open(field_distortion, "rb") as f:
                        self.fdModel = pickle.load(f)
            except AttributeError:
                with pkg_resources.path('ObservationSim.Instrument.data.field_distortion', "FieldDistModelGlobal_mainFP_v1.0.pickle") as field_distortion:
                    with open(field_distortion, "rb") as f:
                        self.fdModel = pickle.load(f)
Fang Yuedong's avatar
Fang Yuedong committed

Fang Yuedong's avatar
Fang Yuedong committed
        # Get boundary (in pix)
        self.bound = self.getChipLim()
Fang Yuedong's avatar
Fang Yuedong committed

Fang Yuedong's avatar
Fang Yuedong committed
        self.ccdEffCurve_dir = ccdEffCurve_dir
        self.CRdata_dir = CRdata_dir
Fang Yuedong's avatar
Fang Yuedong committed

        slsconfs = chip_utils.getChipSLSConf(chipID=self.chipID)
Fang Yuedong's avatar
Fang Yuedong committed
        if np.size(slsconfs) == 1:
            try:
                with pkg_resources.files('ObservationSim.Instrument.data.sls_conf').joinpath(slsconfs) as conf_path:
                    self.sls_conf = str(conf_path)
            except AttributeError:
                with pkg_resources.path('ObservationSim.Instrument.data.sls_conf', slsconfs) as conf_path:
                    self.sls_conf = str(conf_path)
Fang Yuedong's avatar
Fang Yuedong committed
        else:
            # self.sls_conf = [os.path.join(self.sls_dir, slsconfs[0]), os.path.join(self.sls_dir, slsconfs[1])]
            self.sls_conf = []
            try:
                with pkg_resources.files('ObservationSim.Instrument.data.sls_conf').joinpath(slsconfs[0]) as conf_path:
                    self.sls_conf.append(str(conf_path))
            except AttributeError:
                with pkg_resources.path('ObservationSim.Instrument.data.sls_conf', slsconfs[0]) as conf_path:
                    self.sls_conf.append(str(conf_path))
            try:
                with pkg_resources.files('ObservationSim.Instrument.data.sls_conf').joinpath(slsconfs[1]) as conf_path:
                    self.sls_conf.append(str(conf_path))
            except AttributeError:
                with pkg_resources.path('ObservationSim.Instrument.data.sls_conf', slsconfs[1]) as conf_path:
                    self.sls_conf.append(str(conf_path))
Fang Yuedong's avatar
Fang Yuedong committed
        self.effCurve = self._getChipEffCurve(self.filter_type)
        self._getCRdata()

        # # Define the sensor model
        self.sensor = galsim.Sensor()
Fang Yuedong's avatar
Fang Yuedong committed

Fang Yuedong's avatar
Fang Yuedong committed
        self.flat_cube = None  # for spectroscopic flat field cube simulation
Fang Yuedong's avatar
Fang Yuedong committed
    def _set_attributes_from_config(self, config):
        # Default setting
        self.read_noise = 5.0   # e/pix
        self.dark_noise = 0.02  # e/pix/s
        self.rotate_angle = 0.
Fang Yuedong's avatar
Fang Yuedong committed
        self.overscan = 1000
Fang Yuedong's avatar
Fang Yuedong committed
        # Override default values
        # for key in ["gain", "bias_level, dark_exptime", "flat_exptime", "readout_time", "full_well", "read_noise", "dark_noise", "overscan"]:
        #     if key in config["ins_effects"]:
        #         setattr(self, key, config["ins_effects"][key])
Fang Yuedong's avatar
Fang Yuedong committed

Fang Yuedong's avatar
Fang Yuedong committed
    def _getChipRowCol(self):
        self.rowID, self.colID = self.getChipRowCol(self.chipID)

    def getChipRowCol(self, chipID):
        rowID = ((chipID - 1) % 5) + 1
        colID = 6 - ((chipID - 1) // 5)
        return rowID, colID

    def _getSurveyType(self):
        if self.filter_type in _util.SPEC_FILTERS:
Fang Yuedong's avatar
Fang Yuedong committed
            return "spectroscopic"
        elif self.filter_type in _util.PHOT_FILTERS:
Fang Yuedong's avatar
Fang Yuedong committed
            return "photometric"
Fang Yuedong's avatar
Fang Yuedong committed
        # elif self.filter_type in ["FGS"]:
        #     return "FGS"
Fang Yuedong's avatar
Fang Yuedong committed

    def _getChipEffCurve(self, filter_type):
        # CCD efficiency curves
Fang Yuedong's avatar
Fang Yuedong committed
        if filter_type in ['NUV', 'u', 'GU']:
            filename = 'UV0.txt'
        if filter_type in ['g', 'r', 'GV', 'FGS']:
            # TODO, need to switch to the right efficiency curvey for FGS CMOS
            filename = 'Astro_MB.txt'
        if filter_type in ['i', 'z', 'y', 'GI']:
            filename = 'Basic_NIR.txt'
        try:
            with pkg_resources.files('ObservationSim.Instrument.data.ccd').joinpath(filename) as ccd_path:
                table = Table.read(ccd_path, format='ascii')
        except AttributeError:
            with pkg_resources.path('ObservationSim.Instrument.data.ccd', filename) as ccd_path:
                table = Table.read(ccd_path, format='ascii')
Fang Yuedong's avatar
Fang Yuedong committed
        throughput = galsim.LookupTable(
            x=table['col1'], f=table['col2'], interpolant='linear')
Fang Yuedong's avatar
Fang Yuedong committed
        bandpass = galsim.Bandpass(throughput, wave_type='nm')
        return bandpass

    def _getCRdata(self):
        try:
            with pkg_resources.files('ObservationSim.Instrument.data').joinpath("wfc-cr-attachpixel.dat") as cr_path:
                self.attachedSizes = np.loadtxt(cr_path)
        except AttributeError:
            with pkg_resources.path('ObservationSim.Instrument.data', "wfc-cr-attachpixel.dat") as cr_path:
                self.attachedSizes = np.loadtxt(cr_path)
Fang Yuedong's avatar
Fang Yuedong committed
    # def loadSLSFLATCUBE(self, flat_fn='flat_cube.fits'):
    #     try:
    #         with pkg_resources.files('ObservationSim.Instrument.data').joinpath(flat_fn) as data_path:
    #             flat_fits = fits.open(data_path, ignore_missing_simple=True)
    #     except AttributeError:
    #         with pkg_resources.path('ObservationSim.Instrument.data', flat_fn) as data_path:
    #             flat_fits = fits.open(data_path, ignore_missing_simple=True)

    #     fl = len(flat_fits)
    #     fl_sh = flat_fits[0].data.shape
    #     assert fl == 4, 'FLAT Field Cube is Not 4 layess!!!!!!!'
    #     self.flat_cube = np.zeros([fl, fl_sh[0], fl_sh[1]])
    #     for i in np.arange(0, fl, 1):
    #         self.flat_cube[i] = flat_fits[i].data
Fang Yuedong's avatar
Fang Yuedong committed

    def getChipFilter(self, chipID=None):
Fang Yuedong's avatar
Fang Yuedong committed
        """Return the filter index and type for a given chip #(chipID)
        """
Fang Yuedong's avatar
Fang Yuedong committed
        if chipID == None:
            chipID = self.chipID

        # updated configurations
Fang Yuedong's avatar
Fang Yuedong committed
        if chipID > 42 or chipID < 1:
            raise ValueError("!!! Chip ID: [1,42]")
Loading
Loading full blame…