Пример #1
0
def load_wcs(input_model, reference_files=None):
    """ Create a gWCS object and store it in ``Model.meta``.

    Parameters
    ----------
    input_model : `~roman_datamodels.datamodels.WfiImage`
        The exposure.
    reference_files : dict
        A dict {reftype: reference_file_name} containing all
        reference files that apply to this exposure.

    Returns
    -------
    output_model : `~roman_datamodels.ImageModel`
        The input image file with attached gWCS object.
        The data is not modified.
    """
    output_model = input_model.copy()

    if reference_files is not None:
        for ref_type, ref_file in reference_files.items():
            if ref_file not in ["N/A", ""]:
                reference_files[ref_type] = ref_file
            else:
                reference_files[ref_type] = None
    else:
        reference_files = {}

    # Frames
    detector = cf.Frame2D(name='detector',
                          axes_order=(0, 1),
                          unit=(u.pix, u.pix))
    v2v3 = cf.Frame2D(name='v2v3',
                      axes_order=(0, 1),
                      axes_names=('v2', 'v3'),
                      unit=(u.arcsec, u.arcsec))
    world = cf.CelestialFrame(reference_frame=coord.ICRS(), name='world')

    # Transforms between frames
    distortion = wfi_distortion(output_model, reference_files)
    tel2sky = pointing.v23tosky(output_model)

    pipeline = [
        Step(detector, distortion),
        Step(v2v3, tel2sky),
        Step(world, None)
    ]
    wcs = WCS(pipeline)
    if wcs.bounding_box is None:
        wcs.bounding_box = wcs_bbox_from_shape(output_model.data.shape)

    output_model.meta['wcs'] = wcs
    output_model.meta.cal_step['assign_wcs'] = 'COMPLETE'

    return output_model
Пример #2
0
    def _generate_wcs_transform(dispaxis):
        """Create mock gwcs.WCS object for resampled s2d data"""
        detector = cf.Frame2D(name='detector',
                              axes_order=(0, 1),
                              unit=(u.pix, u.pix))
        icrs = cf.CelestialFrame(name='icrs',
                                 reference_frame=coord.ICRS(),
                                 axes_order=(0, 1),
                                 unit=(u.deg, u.deg),
                                 axes_names=('RA', 'DEC'))
        spec = cf.SpectralFrame(name='spec',
                                axes_order=(2, ),
                                unit=(u.micron, ),
                                axes_names=('lambda', ))
        world = cf.CompositeFrame(name="world", frames=[icrs, spec])

        if dispaxis == 1:
            mapping = models.Mapping((0, 1, 0))
        if dispaxis == 2:
            mapping = models.Mapping((0, 1, 1))

        transform = mapping | (models.Const1D(42) & models.Const1D(42)
                               & (models.Shift(30) | models.Scale(0.1)))
        pipeline = [(detector, transform), (world, None)]
        wcs = WCS(pipeline)

        return wcs
Пример #3
0
def load_wcs(input_model, reference_files={}):
    """
    Create the WCS object from the input model and reference files and
    store the pickled WCS-related object into the model meta data.
    """
    if reference_files:
        for ref_type, ref_file in reference_files.items():
            if ref_file not in ["N/A", ""]:
                reference_files[ref_type] = ref_file
            else:
                reference_files[ref_type] = None
    if not any(reference_files.values()):
        log.critical(
            "assign_wcs needs reference files to compute the WCS, none were passed"
        )
        raise ValueError(
            "assign_wcs needs reference files to compute the WCS, none were passed"
        )
    instrument = input_model.meta.instrument.name.lower()
    mod = importlib.import_module('.' + instrument, 'jwst.assign_wcs')

    pipeline = mod.create_pipeline(input_model, reference_files)
    # Initialize the output model as a copy of the input
    # Make the copy after the WCS pipeline is created in order to pass updates to the model.
    if pipeline is None:
        input_model.meta.cal_step.assign_wcs = 'SKIPPED'
        log.warning("SKIPPED assign_wcs")
        return input_model
    else:
        output_model = input_model.copy()
        wcs = WCS(pipeline)
        output_model.meta.wcs = wcs
        output_model.meta.cal_step.assign_wcs = 'COMPLETE'
        log.info("COMPLETED assign_wcs")
    return output_model
Пример #4
0
def generate_s3d_wcs():
    """ create a fake gwcs for a cube """
    # create input /output frames
    detector = cf.CoordinateFrame(name='detector', axes_order=(0,1,2), axes_names=['x', 'y', 'z'],
                                  axes_type=['spatial', 'spatial', 'spatial'], naxes=3,
                                  unit=['pix', 'pix', 'pix'])
    sky = cf.CelestialFrame(reference_frame=coord.ICRS(), name='sky', axes_names=("RA", "DEC"))
    spec = cf.SpectralFrame(name='spectral', unit=['um'], axes_names=['wavelength'], axes_order=(2,))
    world = cf.CompositeFrame(name="world", frames=[sky, spec])

    # create fake transform to at least get a bounding box
    # for the s3d jwst loader

    # shape 30,10,10 (spec, y, x)
    crpix1, crpix2, crpix3 = 5, 5, 15  # (x, y, spec)
    crval1, crval2, crval3 = 1, 1, 1
    cdelt1, cdelt2, cdelt3 = 0.01, 0.01, 0.05

    shift = models.Shift(-crpix2) & models.Shift(-crpix1)
    scale = models.Multiply(cdelt2) & models.Multiply(cdelt1)
    proj = models.Pix2Sky_TAN()
    skyrot = models.RotateNative2Celestial(crval2, 90 + crval1, 180)
    celestial = shift | scale | proj | skyrot
    wave_model = models.Shift(-crpix3) | models.Multiply(cdelt3) | models.Shift(crval3)
    transform = models.Mapping((2, 0, 1)) | celestial & wave_model | models.Mapping((1, 2, 0))
    # bounding box based on shape (30,10,10) in test
    transform.bounding_box = ((0, 29), (0, 9), (0, 9))

    # create final wcs
    pipeline = [(detector, transform),
                (world, None)]
    return WCS(pipeline)
Пример #5
0
def load_wcs(input_model, reference_files={}):
    """
    Create the WCS object from the input model and reference files and
    store the pickled WCS-related object into the model meta data.
    """
    if reference_files:
        for ref_type, ref_file in reference_files.items():
            if ref_file not in ["N/A", ""]:
                reference_files[ref_type] = ref_file
            else:
                reference_files[ref_type] = None
    if not any(reference_files.values()):
        log.critical(
            "assign_wcs needs reference files to compute the WCS, none were passed"
        )
        raise ValueError(
            "assign_wcs needs reference files to compute the WCS, none were passed"
        )
    instrument = input_model.meta.instrument.name.lower()
    mod = importlib.import_module('.' + instrument, 'jwst.assign_wcs')

    # Add WCS keywords for the spectral axis.
    if input_model.meta.wcsinfo.wcsaxes == 3:
        _add_3rd_axis(input_model)

    pipeline = mod.create_pipeline(input_model, reference_files)

    # Initialize the output model as a copy of the input
    # Make the copy after the WCS pipeline is created in order to pass updates to the model.
    if pipeline is None:
        input_model.meta.cal_step.assign_wcs = 'SKIPPED'
        log.warning("assign_wcs: SKIPPED")
        return input_model
    else:
        output_model = input_model.copy()
        wcs = WCS(pipeline)
        output_model.meta.wcs = wcs
        output_model.meta.cal_step.assign_wcs = 'COMPLETE'
        exclude_types = [
            'NRS_FIXEDSLIT', 'NRS_BRIGHTOBJ', 'NRS_IFU', 'NRS_MSASPEC',
            'NRS_LAMP', 'MIR_MRS', 'NIS_SOSS', 'NRC_GRISM', 'NRC_TSGRISM',
            'NIS_WFSS'
        ]

        if output_model.meta.exposure.type not in exclude_types:
            orig_s_region = output_model.meta.wcsinfo.s_region.strip()
            update_s_region(output_model)
            if orig_s_region != output_model.meta.wcsinfo.s_region.strip():
                log.info("assign_wcs updated S_REGION to {0}".format(
                    output_model.meta.wcsinfo.s_region))
        else:
            log.info("assign_wcs did not update S_REGION for type {0}".format(
                output_model.meta.exposure.type))
        log.info("COMPLETED assign_wcs")
    return output_model
Пример #6
0
def load_wcs(input_model, reference_files={}):
    """
    Create a gWCS object and store it in ``Model.meta``.

    Parameters
    ----------
    input_model : `~jwst.datamodels.DataModel`
        The exposure.
    reference_files : dict
        A dict {reftype: reference_file_name} containing all
        reference files that apply to this exposure.
    """

    if "wcsinfo" not in input_model.meta:
        input_model.meta.cal_step.assign_wcs = "SKIPPED"
        log.warning("assign_wcs: SKIPPED")
        return input_model
    else:
        output_model = input_model.copy()
        shift_by_crpix = models.Shift(
            -(input_model.meta.wcsinfo.crpix1 - 1) * u.pix
        ) & models.Shift(-(input_model.meta.wcsinfo.crpix2 - 1) * u.pix)
        pix2sky = getattr(
            models, "Pix2Sky_{}".format(input_model.meta.wcsinfo.ctype1[-3:])
        )()
        celestial_rotation = models.RotateNative2Celestial(
            input_model.meta.wcsinfo.crval1 * u.deg,
            input_model.meta.wcsinfo.crval2 * u.deg,
            180 * u.deg,
        )
        pix2sky.input_units_equivalencies = {
            "x": u.pixel_scale(input_model.meta.wcsinfo.cdelt1 * u.deg / u.pix),
            "y": u.pixel_scale(input_model.meta.wcsinfo.cdelt2 * u.deg / u.pix),
        }
        det2sky = shift_by_crpix | pix2sky | celestial_rotation
        det2sky.name = "linear_transform"
        detector_frame = cf.Frame2D(
            name="detector", axes_names=("x", "y"), unit=(u.pix, u.pix)
        )
        sky_frame = cf.CelestialFrame(
            reference_frame=getattr(
                coord, input_model.meta.coordinates.reference_frame
            )(),
            name="sky_frame",
            unit=(u.deg, u.deg),
        )
        pipeline = [(detector_frame, det2sky), (sky_frame, None)]

        wcs = WCS(pipeline)
        output_model.meta.wcs = wcs
        output_model.meta.cal_step.assign_wcs = "COMPLETE"
    return output_model
Пример #7
0
def create_spectral_wcs(ra, dec, wavelength):
    """Assign a WCS for sky coordinates and a table of wavelengths

    Parameters
    ----------
    ra: float
        The right ascension (in degrees) at the nominal location of the
        entrance aperture (slit).

    dec: float
        The declination (in degrees) at the nominal location of the
        entrance aperture.

    wavelength: ndarray
        The wavelength in microns at each pixel of the extracted spectrum.

    Returns:
    --------
    wcs: a gwcs.wcs.WCS object
        This takes a float or sequence of float and returns a tuple of
        the right ascension, declination, and wavelength (or sequence of
        wavelengths) at the pixel(s) specified by the input argument.
    """

    # Only the first coordinate is used.
    input_frame = cf.Frame2D(axes_order=(0, 1),
                             unit=(u.pix, u.pix),
                             name="pixel_frame")

    sky = cf.CelestialFrame(name='sky',
                            axes_order=(0, 1),
                            reference_frame=coord.ICRS())
    spec = cf.SpectralFrame(name='spectral',
                            axes_order=(2, ),
                            unit=(u.micron, ),
                            axes_names=('wavelength', ))

    pixel = np.arange(len(wavelength), dtype=np.float)
    tab = Mapping((0, 0, 0)) | \
          Const1D(ra) & Const1D(dec) & Tabular1D(pixel, wavelength)

    world = cf.CompositeFrame([sky, spec], name='world')

    pipeline = [(input_frame, tab), (world, None)]

    return WCS(pipeline)
Пример #8
0
def load_wcs(input_model, reference_files={}, nrs_slit_y_range=None):
    """
    Create a gWCS object and store it in ``Model.meta``.

    Parameters
    ----------
    input_model : `~jwst.datamodels.DataModel`
        The exposure.
    reference_files : dict
        A dict {reftype: reference_file_name} containing all
        reference files that apply to this exposure.
    nrs_slit_y_range : list
        The slit y-range for a Nirspec slit. The center is (0, 0).
    """
    if reference_files:
        for ref_type, ref_file in reference_files.items():
            if ref_file not in ["N/A", ""]:
                reference_files[ref_type] = ref_file
            else:
                reference_files[ref_type] = None
    if not any(reference_files.values()):
        log.critical(
            "assign_wcs needs reference files to compute the WCS, none were passed"
        )
        raise ValueError(
            "assign_wcs needs reference files to compute the WCS, none were passed"
        )
    instrument = input_model.meta.instrument.name.lower()
    mod = importlib.import_module('.' + instrument, 'jwst.assign_wcs')

    if input_model.meta.exposure.type.lower() in SPEC_TYPES:
        input_model.meta.wcsinfo.specsys = "BARYCENT"
        input_model.meta.wcsinfo.dispersion_direction = \
                        get_dispersion_direction(
                                input_model.meta.exposure.type,
                                input_model.meta.instrument.grating,
                                input_model.meta.instrument.filter,
                                input_model.meta.instrument.pupil)

    if instrument.lower() == 'nirspec':
        pipeline = mod.create_pipeline(input_model,
                                       reference_files,
                                       slit_y_range=nrs_slit_y_range)
    else:
        pipeline = mod.create_pipeline(input_model, reference_files)
    # Initialize the output model as a copy of the input
    # Make the copy after the WCS pipeline is created in order to pass updates to the model.
    if pipeline is None:
        input_model.meta.cal_step.assign_wcs = 'SKIPPED'
        log.warning("assign_wcs: SKIPPED")
        return input_model
    else:
        output_model = input_model.copy()
        wcs = WCS(pipeline)
        output_model.meta.wcs = wcs
        output_model.meta.cal_step.assign_wcs = 'COMPLETE'
        exclude_types = [
            'nrc_wfss', 'nrc_tsgrism', 'nis_wfss', 'nrs_fixedslit',
            'nrs_msaspec', 'nrs_autowave', 'nrs_autoflat', 'nrs_lamp',
            'nrs_brightobj', 'nis_soss'
        ]

        if output_model.meta.exposure.type.lower() not in exclude_types:
            imaging_types = IMAGING_TYPES.copy()
            imaging_types.update(['mir_lrs-fixedslit', 'mir_lrs-slitless'])
            if output_model.meta.exposure.type.lower() in imaging_types:
                try:
                    update_s_region_imaging(output_model)
                except Exception as exc:
                    log.error(
                        "Unable to update S_REGION for type {}: {}".format(
                            output_model.meta.exposure.type, exc))
                else:
                    log.info("assign_wcs updated S_REGION to {0}".format(
                        output_model.meta.wcsinfo.s_region))
            elif output_model.meta.exposure.type.lower() == "nrs_ifu":
                update_s_region_nrs_ifu(output_model, mod)
            elif output_model.meta.exposure.type.lower() == 'mir_mrs':
                update_s_region_mrs(output_model)
            else:
                try:
                    update_s_region_spectral(output_model)
                except Exception as exc:
                    log.info(
                        "Unable to update S_REGION for type {}: {}".format(
                            output_model.meta.exposure.type, exc))
    log.info("COMPLETED assign_wcs")
    return output_model
Пример #9
0
def flag(input_datamodel, failed_slitlets, wcs_refnames):
    """
    Takes the list of failed open shutters from the failedopen reference file
    and calculates the pixels affected using the WCS model.
    The affected pixels in the science data have their DQ flags combined with
    that for the MSA_FAILED_OPEN standard flag.  All other science data
    arrays are unchanged.

    Parameters
    ----------
    input_datamodel: data model object
        the input science data

    failed_slitlets: list
        List of failed open slitlets

    wcs_refnames: dict
        dictionary of reference file names used to calculate the WCS

    Returns
    -------
    input_datamodel: data model object
        science data with DQ flags of affected modified

    """
    #
    # Use the machinery in assign_wcs to create a WCS object for the bad shutters
    pipeline = slitlets_wcs(input_datamodel, wcs_refnames, failed_slitlets)
    wcs = WCS(pipeline)
    # Create output as a copy of the input science data model so we can overwrite
    # the wcs with the wcs for the failed open shutters
    temporary_copy = input_datamodel.copy()
    temporary_copy.meta.wcs = wcs
    dq_array = input_datamodel.dq
    for slitlet in failed_slitlets:
        #
        # Pick the WCS for this slitlet from the WCS of the exposure
        thiswcs = nrs_wcs_set_input(temporary_copy, slitlet.name)
        #
        # Convert the bounding box for this slitlet to a set of indices to use as a slice
        xmin, xmax, ymin, ymax = boundingbox_to_indices(
            temporary_copy, thiswcs.bounding_box)
        #
        # Make a grid of points within the slice
        y_indices, x_indices = np.mgrid[ymin:ymax, xmin:xmax]
        #
        # Calculate the arrays of coordinates for each pixel in the slice
        coordinate_array = thiswcs(x_indices, y_indices)
        #
        # The coordinate_array is a tuple of arrays, one for each output coordinate
        # In this case there should be 3 arrays, one each for RA, Dec and Wavelength
        # For pixels outside the slitlet, the arrays have NaN
        #
        # Make a subarray from these coordinate arrays by setting pixels that aren't
        # NaN to FAILDOPENFLAG, the rest to 0
        dq_subarray = wcs_to_dq(coordinate_array, FAILEDOPENFLAG)
        #
        # bitwise-or this subarray with the slice in the original exposure's DQ array
        dq_array = or_subarray_with_array(dq_array, dq_subarray, xmin, xmax,
                                          ymin, ymax)
    #
    # Set the dq array of the input datamodel to the corrected dq array
    input_datamodel.dq = dq_array
    return input_datamodel
Пример #10
0
def load_wcs(input_model, reference_files={}):
    """
    Create a gWCS object and store it in ``Model.meta``.

    Parameters
    ----------
    input_model : `~jwst.datamodels.DataModel`
        The exposure.
    reference_files : dict
        A dict {reftype: reference_file_name} containing all
        reference files that apply to this exposure.
    """
    if reference_files:
        for ref_type, ref_file in reference_files.items():
            if ref_file not in ["N/A", ""]:
                reference_files[ref_type] = ref_file
            else:
                reference_files[ref_type] = None
    if not any(reference_files.values()):
        log.critical(
            "assign_wcs needs reference files to compute the WCS, none were passed"
        )
        raise ValueError(
            "assign_wcs needs reference files to compute the WCS, none were passed"
        )
    instrument = input_model.meta.instrument.name.lower()
    mod = importlib.import_module('.' + instrument, 'jwst.assign_wcs')

    # Add WCS keywords for the spectral axis.
    if input_model.meta.wcsinfo.wcsaxes == 3:
        _add_3rd_axis(input_model)

    if input_model.meta.exposure.type.lower() in SPEC2_SCIENCE_EXP_TYPES:
        input_model.meta.wcsinfo.specsys = "BARYCENT"

    pipeline = mod.create_pipeline(input_model, reference_files)

    # Initialize the output model as a copy of the input
    # Make the copy after the WCS pipeline is created in order to pass updates to the model.
    if pipeline is None:
        input_model.meta.cal_step.assign_wcs = 'SKIPPED'
        log.warning("assign_wcs: SKIPPED")
        return input_model
    else:
        output_model = input_model.copy()
        wcs = WCS(pipeline)
        output_model.meta.wcs = wcs
        output_model.meta.cal_step.assign_wcs = 'COMPLETE'
        exclude_types = [
            'nrc_wfss', 'nrc_tsgrism', 'nis_wfss', 'nrs_fixedslit', 'nrs_ifu',
            'nrs_msaspec', 'nrs_autowave', 'nrs_autoflat', 'nrs_lamp',
            'nrs_brightobj', 'mir_lrs-fixedslit', 'mir_lrs-slitless',
            'mir_mrs', 'nis_soss'
        ]

        if output_model.meta.exposure.type.lower() not in exclude_types:
            if output_model.meta.exposure.type.lower() in IMAGING_TYPES:
                try:
                    update_s_region_imaging(output_model)
                except Exception as exc:
                    log.error(
                        "Unable to update S_REGION for type {}: {}".format(
                            output_model.meta.exposure.type, exc))
                else:
                    log.info("assign_wcs updated S_REGION to {0}".format(
                        output_model.meta.wcsinfo.s_region))
            else:
                try:
                    update_s_region_spectral(output_model)
                except Exception as exc:
                    log.info(
                        "Unable to update S_REGION for type {}: {}".format(
                            output_model.meta.exposure.type, exc))
    log.info("COMPLETED assign_wcs")
    return output_model
Пример #11
0
def create_spectral_wcs(ra, dec, wavelength):
    """Assign a WCS for sky coordinates and a table of wavelengths

    Parameters
    ----------
    ra: float
        The right ascension (in degrees) at the nominal location of the
        entrance aperture (slit).

    dec: float
        The declination (in degrees) at the nominal location of the
        entrance aperture.

    wavelength: ndarray
        The wavelength in microns at each pixel of the extracted spectrum.

    Returns:
    --------
    wcs: a gwcs.wcs.WCS object
        This takes a float or sequence of float and returns a tuple of
        the right ascension, declination, and wavelength (or sequence of
        wavelengths) at the pixel(s) specified by the input argument.
    """

    input_frame = cf.CoordinateFrame(naxes=1,
                                     axes_type=("SPATIAL", ),
                                     axes_order=(0, ),
                                     unit=(u.pix, ),
                                     name="pixel_frame")

    sky = cf.CelestialFrame(name='sky',
                            axes_order=(0, 1),
                            reference_frame=coord.ICRS())
    spec = cf.SpectralFrame(name='spectral',
                            axes_order=(2, ),
                            unit=(u.micron, ),
                            axes_names=('wavelength', ))
    world = cf.CompositeFrame([sky, spec], name='world')

    pixel = np.arange(len(wavelength), dtype=np.float)
    tab = Mapping((0, 0, 0)) | \
          Const1D(ra) & Const1D(dec) & Tabular1D(points=pixel,
                                                 lookup_table=wavelength,
                                                 bounds_error=False,
                                                 fill_value=None)
    tab.name = "pixel_to_world"

    if all(np.diff(wavelength) > 0):
        tab.inverse = Mapping((2, )) | Tabular1D(
            points=wavelength,
            lookup_table=pixel,
            bounds_error=False,
        )
    elif all(np.diff(wavelength) < 0):
        tab.inverse = Mapping((2, )) | Tabular1D(
            points=wavelength[::-1],
            lookup_table=pixel[::-1],
            bounds_error=False,
        )
    else:
        log.warning(
            "Wavelengths are not strictly monotonic, inverse transform is not set"
        )

    pipeline = [(input_frame, tab), (world, None)]

    return WCS(pipeline)