Exemplo n.º 1
0
def get_JWST_pixel_scale(meta, aperture=None):
    """Use pysiaf to find the nominal pixel scale for a given JWST
    instrument/detector

    Parameters
    ----------
    meta : dict
        Dictionary of instrument information. Most important is
        meta['channel'] which contains the integer IRAC channel
        number. PSFs are loaded from photutils

    aperture : str
        Name of aperture to look up pixel scale for. If None,
        then fall back to using FULL or CEN as appropriate.

    Returns
    -------
    siaf_aper.XSciScale : float
        Pixel scale (arcsec/pixel) in x-direction on detector

    siaf_aper.YSciScale : float
        Pixel scale (arcsec/pixel) in y-direction on detector
    """
    # Create SIAF instance
    siaf = get_instance(meta['instrument'])

    # If needed, get the name to append to the detector to create
    # the full aperture
    # name
    if aperture is None:
        if meta['instrument'].lower() == 'nircam':
            aperture = 'FULL'
        elif meta['instrument'].lower() == 'niriss':
            aperture = 'CEN'
        elif meta['instrument'].lower() == 'fgs':
            aperture = 'FULL'

        # In SIAF, the FGS detectors are FGS1,2 rather than GUIDER1,2
        detector = meta['detector'].upper()
        if 'GUIDER' in detector:
            detector = detector.replace('GUIDER', 'FGS')

        aperture = '{}_{}'.format(detector, aperture)

    # Get the aperture-specific SIAF info
    siaf_aper = siaf[aperture]

    # Return the x and y pixel scale
    return siaf_aper.XSciScale, siaf_aper.YSciScale
Exemplo n.º 2
0
    def blot(self):
        """MAIN FUNCTION
        Resamples the input image onto the WCS associated with the given
        instrument/apertures
        """
        # Get detector names from the aperture list
        if isinstance(self.aperture, str):
            self.aperture = [self.aperture]

        self.detector = [element.split('_')[0] for element in self.aperture]

        # Make sure detector, ra, dec, and roll have same number
        # of elements
        if ((len(self.center_dec) != len(self.center_ra)) | \
                (len(self.center_dec) != len(self.pav3))):
            raise ValueError(('WARNING: center_ra, center_dec '
                              'and pav3 all must have the same number '
                              'of elements.'))

        if type(self.blotfile) == str:
            input_mod = datamodels.ImageModel(self.blotfile)
            outbase = self.blotfile

        elif type(self.blotfile) == datamodels.image.ImageModel:
            # Not a great solution at the moment. Save
            # imagemodel instance so that you have a fits
            # file from which the header can be retrieved
            input_mod = copy(self.blotfile)
            self.blotfile.save('temp.fits')
            self.blotfile = 'temp.fits'
            outbase = 'mosaic'

        else:
            raise ValueError('WARNING: unrecognized type for blotfile')

        # Create a GWCS object from the input file's header
        input_header = fits.getheader(self.blotfile, ext=1)
        transform = gwcs.utils.make_fitswcs_transform(input_header)
        input_mod.meta.wcs = gwcs.WCS(forward_transform=transform,
                                      output_frame='world')

        # Filter and pupil information
        filtername = input_mod.meta.instrument.filter
        try:
            pupil = input_mod.meta.instrument.pupil
        except:
            pupil = 'CLEAR'

        # Get position angle of input data
        input_pav3 = input_mod.meta.wcsinfo.roll_ref

        # Name of temporary file output for set_telescope_pointing
        # to work on
        shellname = 'temp_wcs_container.fits'

        blist = []
        for (aper, det, ra, dec, roll) in \
            zip(self.aperture, self.detector, self.center_ra, self.center_dec, self.pav3):
            # Get aperture-specific info
            self.siaf = get_instance(self.instrument)[aper]

            # Create datamodel with appropriate metadata
            bmodel = self.make_model(det, ra, dec, input_pav3, filtername,
                                     pupil)
            bmodel.save(shellname, overwrite=True)

            # Use set_telescope_pointing to compute local roll
            # angle and PC matrix
            stp.add_wcs(shellname, roll=roll)

            bmodel = datamodels.open(shellname)

            # Now we need to run assign_wcs step so that these
            # files get a gwcs object attached to them.
            if self.distortion_file is not None:
                bmodel = AssignWcsStep.call(
                    bmodel, override_distortion=self.distortion_file)
            else:
                bmodel = AssignWcsStep.call(bmodel)

            # Add to the list of data model instances to blot to
            blist.append(bmodel)

        # Place the model instances to blot to in a ModelContainer
        blot_list = container.ModelContainer(blist)

        # Blot the image to each of the WCSs in the blot_list
        pars = {'sinscl': 1.0, 'interp': 'poly5'}
        reffiles = {}
        blotter = outlier_detection.OutlierDetection(blot_list,
                                                     reffiles=reffiles,
                                                     **pars)
        blotter.input_models = blot_list
        self.blotted_datamodels = blotter.blot_median(input_mod)
Exemplo n.º 3
0
pointing_ra = 12.0
pointing_dec = 12.0
rotation = 0.0
ra_list = []
dec_list = []
delta_pix = np.array([0, 10, 20, 40, 75, 180, 500, 1000])
delta_deg = delta_pix * 0.031 / 3600.
for delta in delta_deg:
    ra_entry = pointing_ra + delta
    dec_entry = pointing_dec + delta
    ra_list.append(ra_entry)
    dec_list.append(dec_entry)

c = catalog_seed_image.Catalog_seed()
for instrument in instruments:
    siaf = siaf_interface.get_instance(instrument)

    if instrument.lower() == 'nircam':
        a_detectors = ['NRCA{}'.format(i + 1) for i in range(5)]
        b_detectors = ['NRCB{}'.format(i + 1) for i in range(5)]
        detectors = a_detectors + b_detectors
    elif instrument.lower() == 'niriss':
        detectors = ['NIS']
    elif instrument.lower() == 'fgs':
        detectors = ['FGS1', 'FGS2']

    print('\n\nDetectors: {}\n\n'.format(detectors))

    # Find reference files
    reffile_dir = os.path.join(
        data_dir, '{}/reference_files/distortion'.format(instrument))
Exemplo n.º 4
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