Beispiel #1
0
    def read_param_file(self, file):
        """Read the input yaml file into a nested dictionary

        Parameters
        ----------
        file : str
            Name of the input yaml file
        """
        if os.path.isfile(file):
            with open(file, 'r') as f:
                self.params = yaml.safe_load(f)
        else:
            raise FileNotFoundError(("ERROR: {} does not exist.".format(file)))

        self.instrument = self.params['Inst']['instrument'].upper()
        self.aperture = self.params['Readout']['array_name'].upper()
        self.detector_channel_value()

        self.crop_center_ra = self.params['Telescope']['ra']
        self.crop_center_dec = self.params['Telescope']['dec']
        self.blot_center_ra = self.params['Telescope']['ra']
        self.blot_center_dec = self.params['Telescope']['dec']
        self.blot_pav3 = self.params['Telescope']['rotation']

        self.flux_cal_file = self.params['Reffiles']['flux_cal']
        self.distortion_file = self.params['Reffiles']['astrometric']
        self.filter = self.params['Readout']['filter']
        self.pupil = self.params['Readout']['pupil']

        self.output_base = self.params['Output']['file']

        # If input is to be dispersed later, we need to
        # expand the region to be blotted
        if self.params['Output']['grism_source_image']:
            self.grism_coord_adjust()

        if self.outdir is None:
            self.outdir = self.params['Output']['directory']

        # Create a dictionary for future CRDS query
        self.reference_dictionary = crds_tools.dict_from_yaml(self.params)
Beispiel #2
0
    def prepare(self):
        """MAIN FUNCTION"""
        print("\nRunning dark_prep....\n")

        # Read in the yaml parameter file
        self.read_parameter_file()

        # Create dictionary to use when looking in CRDS for reference files
        self.crds_dict = crds_tools.dict_from_yaml(self.params)

        # Expand param entries to full paths where appropriate
        self.pararms = utils.full_paths(self.params,
                                        self.modpath,
                                        self.crds_dict,
                                        offline=self.offline)
        self.filecheck()

        # Base name for output files
        base_name = self.params['Output']['file'].split('/')[-1]
        self.basename = os.path.join(self.params['Output']['directory'],
                                     base_name[0:-5])

        # Check the entered read pattern info
        self.readpattern_check()

        # Check input parameters for any bad values
        self.check_params()

        # Read in the subarray definition file
        self.subdict = utils.read_subarray_definition_file(
            self.params['Reffiles']['subarray_defs'])
        self.params = utils.get_subarray_info(self.params, self.subdict)

        # Get the subarray boundaries from pysiaf
        siaf_inst = self.params['Inst']['instrument']
        instrument_siaf = siaf_interface.get_instance(siaf_inst)
        self.siaf = instrument_siaf[self.params['Readout']['array_name']]
        junk0, junk1, self.ffsize, \
            self.subarray_bounds = siaf_interface.get_siaf_information(instrument_siaf,
                                                                       self.params['Readout']['array_name'],
                                                                       0.0, 0.0,
                                                                       self.params['Telescope']['rotation'])
        # Read in the input dark current frame
        if not self.runStep['linearized_darkfile']:
            self.get_base_dark()
            self.linDark = None
        else:
            self.read_linear_dark()
            self.dark = self.linDark

        # Make sure there is enough data (frames/groups)
        # in the input integration to produce
        # the proposed output integration
        self.data_volume_check(self.dark)

        # Compare the requested number of integrations
        # to the number of integrations in the input dark
        print("Dark shape as read in: {}".format(self.dark.data.shape))
        self.darkints()
        print("Dark shape after copying integrations to match request: {}".
              format(self.dark.data.shape))

        # Put the input dark (or linearized dark) into the
        # requested readout pattern
        self.dark, sbzeroframe = self.reorder_dark(self.dark)
        print((
            'DARK has been reordered to {} to match the input readpattern of {}'
            .format(self.dark.data.shape, self.dark.header['READPATT'])))

        # If a raw dark was read in, create linearized version
        # here using the SSB pipeline. Better to do this
        # on the full dark before cropping, so that reference
        # pixels can be used in the processing.
        if ((self.params['Inst']['use_JWST_pipeline']) &
            (self.runStep['linearized_darkfile'] is False)):

            # Linear ize the dark ramp via the SSB pipeline.
            # Also save a diff image of the original dark minus
            # the superbias and refpix subtracted dark, to use later.

            # In order to linearize the dark, the JWST pipeline must
            # be present, and self.dark will have to be translated back
            # into a RampModel instance
            # print('Working on {}'.format(self.dark))
            self.linDark = self.linearize_dark(self.dark)
            print("Linearized dark shape: {}".format(self.linDark.data.shape))

            if self.params['Readout']['readpatt'].upper() in [
                    'RAPID', 'NISRAPID', 'FGSRAPID'
            ]:
                print(
                    ("Output is {}, grabbing zero frame from linearized dark".
                     format(self.params['Readout']['readpatt'].upper())))
                self.zeroModel = read_fits.Read_fits()
                self.zeroModel.data = self.linDark.data[:, 0, :, :]
                self.zeroModel.sbAndRefpix = self.linDark.sbAndRefpix[:,
                                                                      0, :, :]
            elif ((self.params['Readout']['readpatt'].upper()
                   not in ['RAPID', 'NISRAPID', 'FGSRAPID']) &
                  (self.dark.zeroframe is not None)):
                print("Now we need to linearize the zeroframe because the")
                print("output readpattern is not RAPID, NISRAPID, or FGSRAPID")
                # Now we need to linearize the zeroframe. Place it
                # into a RampModel instance before running the
                # pipeline steps
                self.zeroModel = read_fits.Read_fits()
                self.zeroModel.data = np.expand_dims(self.dark.zeroframe,
                                                     axis=1)
                self.zeroModel.header = self.linDark.header
                self.zeroModel.header['NGROUPS'] = 1
                self.zeroModel = self.linearize_dark(self.zeroModel)
                # Return the zeroModel data to 3 dimensions
                # integrations, y, x
                self.zeroModel.data = self.zeroModel.data[:, 0, :, :]
                self.zeroModel.sbAndRefpix = self.zeroModel.sbAndRefpix[:,
                                                                        0, :, :]
                # In this case the zeroframe has changed from what
                # was read in. So let's remove the original zeroframe
                # to avoid confusion
                self.linDark.zeroframe = np.zeros(self.linDark.zeroframe.shape)
            else:
                self.zeroModel = None

            # Now crop self.linDark, self.dark, and zeroModel
            # to requested subarray
            self.dark = self.crop_dark(self.dark)
            self.linDark = self.crop_dark(self.linDark)

            if self.zeroModel is not None:
                self.zeroModel = self.crop_dark(self.zeroModel)

        elif self.runStep['linearized_darkfile']:
            # If no pipeline is run
            self.zeroModel = read_fits.Read_fits()
            self.zeroModel.data = self.dark.zeroframe
            self.zeroModel.sbAndRefpix = sbzeroframe

            # Crop the linearized dark to the requested
            # subarray size
            # THIS WILL CROP self.dark AS WELL SINCE
            # self.linDark IS JUST A REFERENCE IN THE NON
            # PIPELINE CASE!!
            self.linDark = self.crop_dark(self.linDark)
            if self.zeroModel.data is not None:
                self.zeroModel = self.crop_dark(self.zeroModel)
        else:
            raise NotImplementedError((
                "Mode not yet supported! Must use either: use_JWST_pipeline "
                "= True and a raw or linearized dark or supply a linearized dark. "
                "Cannot yet skip the pipeline and provide a raw dark."))

        # Save the linearized dark
        # if self.params['Output']['save_intermediates']:
        h0 = fits.PrimaryHDU()
        h1 = fits.ImageHDU(self.linDark.data, name='SCI')
        h2 = fits.ImageHDU(self.linDark.sbAndRefpix, name='SBANDREFPIX')
        h3 = fits.ImageHDU(self.zeroModel.data, name='ZEROFRAME')
        h4 = fits.ImageHDU(self.zeroModel.sbAndRefpix, name='ZEROSBANDREFPIX')

        # Populate basic info in the 0th extension header
        nints, ngroups, yd, xd = self.linDark.data.shape
        h0.header['READPATT'] = self.params['Readout']['readpatt'].upper()
        h0.header['NINTS'] = nints
        h0.header['NGROUPS'] = ngroups
        h0.header['NFRAMES'] = self.params['Readout']['nframe']
        h0.header['NSKIP'] = self.params['Readout']['nskip']
        h0.header['DETECTOR'] = self.detector
        h0.header['INSTRUME'] = self.instrument
        h0.header['SLOWAXIS'] = self.slowaxis
        h0.header['FASTAXIS'] = self.fastaxis

        # Add some basic Mirage-centric info
        h0.header['MRGEVRSN'] = (MIRAGE_VERSION, 'Mirage version used')
        h0.header['YAMLFILE'] = (self.paramfile, 'Mirage input yaml file')

        hl = fits.HDUList([h0, h1, h2, h3, h4])
        objname = self.basename + '_linear_dark_prep_object.fits'
        objname = os.path.join(self.params['Output']['directory'], objname)
        hl.writeto(objname, overwrite=True)
        print(("Linearized dark frame plus superbias and reference"
               "pixel signals, as well as zeroframe, saved to {}. "
               "This can be used as input to the observation"
               "generator.".format(objname)))

        # important variables
        # self.linDark
        # self.zeroModel
        # Make a read_fits instance that contains all the important
        # information, for ease in connecting with next step of the
        # simulator
        self.prepDark = read_fits.Read_fits()
        self.prepDark.data = self.linDark.data
        self.prepDark.zeroframe = self.zeroModel.data
        self.prepDark.sbAndRefpix = self.linDark.sbAndRefpix
        self.prepDark.zero_sbAndRefpix = self.zeroModel.sbAndRefpix
        self.prepDark.header = self.linDark.header
    def get_param_info(self):
        """Collect needed information out of the parameter file. Check
        parameter values for correctness

        Returns
        -------
        parameters : dict
            Nested dictionary of parameters in the input yaml file
        """
        self.catalog_files = []
        parameters = utils.read_yaml(self.paramfile)

        # Create dictionary to use when looking in CRDS for reference files
        crds_dict = crds_tools.dict_from_yaml(parameters)

        # Expand reference file entries to be full path names
        parameters = utils.full_paths(parameters, self.modpath, crds_dict)

        try:
            CATALOG_YAML_ENTRIES.remove('tso_grism_catalog')
        except ValueError:
            pass

        try:
            CATALOG_YAML_ENTRIES.remove('tso_imaging_catalog')
        except ValueError:
            pass
        cats = [
            parameters['simSignals'][cattype]
            for cattype in CATALOG_YAML_ENTRIES
        ]
        cats = [e for e in cats if e.lower() != 'none']
        self.catalog_files.extend(cats)

        if len(self.catalog_files) == 0:
            # If no background source catalogs are given, create a dummy point
            # source catalog and add it to the list. Without this, the
            # creation of the final SED file would fail. Put the source
            # down near the SEP and with a magnitude such that it won't
            # disturb anything
            filter_name = parameters['Readout']['filter'].lower()
            dummy_ptsrc = catalog_generator.PointSourceCatalog(ra=[0.],
                                                               dec=[-89.])
            dummy_ptsrc.add_magnitude_column([40],
                                             instrument='nircam',
                                             filter_name=filter_name,
                                             magnitude_system='abmag')
            dummy_cat = 'dummy_ptsrc.cat'
            dummy_ptsrc.save(dummy_cat)
            self.catalog_files.append(dummy_cat)
            parameters['simSignals']['pointsource'] = dummy_cat

        self.instrument = parameters['Inst']['instrument'].lower()
        self.aperture = parameters['Readout']['array_name']
        try:
            self.namps = parameters['Readout']['namp']
        except KeyError:
            pass
        if self.instrument == 'niriss':
            self.module = None
            self.detetor = 'NIS'
        elif self.instrument == 'nircam':
            self.module = parameters['Readout']['array_name'][3]
            self.detector = parameters['Readout']['array_name'][0:5]
        else:
            raise ValueError(
                "ERROR: Grism TSO mode not supported for {}".format(
                    self.instrument))

        filter_name = parameters['Readout']['filter']
        pupil_name = parameters['Readout']['pupil']

        # In reality, the grism elements are in NIRCam's pupil wheel, and NIRISS's
        # filter wheel. But in the APT xml file, NIRISS grisms are in the pupil
        # wheel and the crossing filter is listed in the filter wheel. At that
        # point, NIRISS and NIRCam are consistent, so let's keep with this reversed
        # information
        if self.instrument == 'niriss':
            self.crossing_filter = pupil_name.upper()
            self.dispersion_direction = filter_name[-1].upper()
        elif self.instrument == 'nircam':
            if 'CLEAR' in pupil_name.upper():
                raise ValueError(
                    "ERROR: pupil cannot be CLEAR. It must be GRISMR or GRISMC."
                )
            self.crossing_filter = filter_name.upper()
            self.dispersion_direction = pupil_name[-1].upper()
        return parameters