Esempio n. 1
0
    def get_slitmask(self, filename):
        """
        Parse the slitmask data from a DEIMOS file into a
        :class:`pypeit.spectrographs.slitmask.SlitMask` object.

        Args:
            filename (:obj:`str`):
                Name of the file to read.
        """
        # Open the file
        hdu = fits.open(filename)

        # Build the object data
        #   - Find the index of the object IDs in the slit-object
        #     mapping that match the object catalog
        mapid = hdu['SlitObjMap'].data['ObjectID']
        catid = hdu['ObjectCat'].data['ObjectID']
        indx = index_of_x_eq_y(mapid, catid)
        #   - Pull out the slit ID, object ID, and object coordinates
        objects = np.array([
            hdu['SlitObjMap'].data['dSlitId'][indx].astype(float),
            catid.astype(float), hdu['ObjectCat'].data['RA_OBJ'],
            hdu['ObjectCat'].data['DEC_OBJ']
        ]).T
        #   - Only keep the objects that are in the slit-object mapping
        objects = objects[mapid[indx] == catid]

        # Match the slit IDs in DesiSlits to those in BluSlits
        indx = index_of_x_eq_y(hdu['DesiSlits'].data['dSlitId'],
                               hdu['BluSlits'].data['dSlitId'],
                               strict=True)

        # Instantiate the slit mask object and return it
        self.slitmask = SlitMask(
            np.array([
                hdu['BluSlits'].data['slitX1'], hdu['BluSlits'].data['slitY1'],
                hdu['BluSlits'].data['slitX2'], hdu['BluSlits'].data['slitY2'],
                hdu['BluSlits'].data['slitX3'], hdu['BluSlits'].data['slitY3'],
                hdu['BluSlits'].data['slitX4'], hdu['BluSlits'].data['slitY4']
            ]).T.reshape(-1, 4, 2),
            slitid=hdu['BluSlits'].data['dSlitId'],
            align=hdu['DesiSlits'].data['slitTyp'][indx] == 'A',
            science=hdu['DesiSlits'].data['slitTyp'][indx] == 'P',
            onsky=np.array([
                hdu['DesiSlits'].data['slitRA'][indx],
                hdu['DesiSlits'].data['slitDec'][indx],
                hdu['DesiSlits'].data['slitLen'][indx],
                hdu['DesiSlits'].data['slitWid'][indx],
                hdu['DesiSlits'].data['slitLPA'][indx]
            ]).T,
            objects=objects)
        return self.slitmask
Esempio n. 2
0
    def __init__(self,
                 corners,
                 slitid=None,
                 align=None,
                 science=None,
                 onsky=None,
                 objects=None):

        # TODO: Allow random input order and then fix

        # TODO: Is counter-clockwise order more natural (the order in
        # DEIMOS slitmasks is clockwise, which is why that was chosen
        # here)

        # Convert to a numpy array if it isn't already one
        _corners = numpy.asarray(corners)
        # Check the shape
        if _corners.shape[-1] != 2 or _corners.shape[-2] != 4:
            raise ValueError(
                'Incorrect input shape.  Must provide 4 corners with x and y for '
                'each corner.')
        # Assign corner attribute allowing for one slit on input
        # TODO: Annoyingly, numpy.atleast_3d appends a dimension at the
        # end instead of at the beginning, like what's done with
        # numpy.atleast_2d.
        self.corners = _corners.reshape(1, 4,
                                        2) if _corners.ndim == 2 else _corners

        # Assign the slit IDs
        self.slitid = numpy.arange(self.corners.shape[0]) if slitid is None \
                        else numpy.atleast_1d(slitid)
        # Check the numbers match
        if self.slitid.size != self.corners.shape[0]:
            raise ValueError('Incorrect number of slit IDs provided.')
        if len(numpy.unique(self.slitid)) != len(self.slitid):
            raise ValueError('Slit IDs must be unique!')

        # Set the bitmask
        self.mask = numpy.zeros(self.nslits,
                                dtype=self.bitmask.minimum_dtype())
        if align is not None:
            _align = numpy.atleast_1d(align)
            if _align.size != self.nslits:
                raise ValueError(
                    'Alignment flags must be provided for each slit.')
            self.mask[_align] = self.bitmask.turn_on(self.mask[_align],
                                                     'ALIGN')
        if science is not None:
            _science = numpy.atleast_1d(science)
            if _science.size != self.nslits:
                raise ValueError(
                    'Science-target flags must be provided for each slit.')
            self.mask[_science] = self.bitmask.turn_on(self.mask[_science],
                                                       'SCIENCE')

        # On-sky coordinates of the slit center
        self.onsky = None
        if onsky is not None:
            self.onsky = numpy.atleast_2d(onsky)
            if self.onsky.shape != (self.nslits, 5):
                raise ValueError(
                    'Must provide sky coordinates and slit length, width, and PA '
                    'for each slit.')

        # Expected objects in each slit
        self.objects = None
        self.slitindx = None
        if objects is not None:
            self.objects = numpy.atleast_2d(objects)
            if self.objects.shape[1] != 4:
                raise ValueError(
                    'Must provide the slit ID and sky coordinates for each object.'
                )
            try:
                self.slitindx = index_of_x_eq_y(self.slitid,
                                                self.objects[:, 0].astype(int),
                                                strict=True)
            except:
                # Should only fault if there are slit IDs in `objects`
                # that are not in `slitid`. In that case, return a more
                # sensible error message than what index_of_x_eq_y
                # would provide.
                raise ValueError('Some slit IDs in object list not valid.')

        # Center coordinates
        self.center = numpy.mean(self.corners, axis=1)

        # Top and bottom (assuming the correct input order)
        self.top = numpy.mean(numpy.roll(self.corners, 1, axis=1)[:, 0:2, :],
                              axis=1)
        self.bottom = numpy.mean(self.corners[:, 1:3, :], axis=1)

        # Length and width
        self.length = numpy.absolute(
            numpy.diff(self.corners[:, 0:2, 0], axis=1)).ravel()
        self.width = numpy.absolute(numpy.diff(self.corners[:, 1:3, 1],
                                               axis=1)).ravel()

        # Position angle
        self.pa = numpy.degrees(
            numpy.arctan2(numpy.diff(self.corners[:, 0:2, 1], axis=1),
                          numpy.diff(self.corners[:, 0:2, 0],
                                     axis=1))).ravel()
        self.pa[self.pa < -90] += 180
        self.pa[self.pa > 90] -= 180
Esempio n. 3
0
def load_keck_deimoslris(filename:str, instr:str):
    """ Load up the mask design info from the header
    of the file provided

    Args:
        filename (str): 
        instr (str): Name of spectrograph
            Allowed are keck_lris_xxx, keck_deimos

    Returns:
        [type]: [description]
    """
    # Open the file
    hdu = io.fits_open(filename)

    # Build the object data
    #   - Find the index of the object IDs in the slit-object
    #     mapping that match the object catalog
    mapid = hdu['SlitObjMap'].data['ObjectID']
    catid = hdu['ObjectCat'].data['ObjectID']
    indx = index_of_x_eq_y(mapid, catid)
    objname = [item.strip() for item in hdu['ObjectCat'].data['OBJECT']]
    #   - Pull out the slit ID, object ID, name, object coordinates, top and bottom distance
    objects = numpy.array([hdu['SlitObjMap'].data['dSlitId'][indx].astype(int),
                        catid.astype(int),
                        hdu['ObjectCat'].data['RA_OBJ'],
                        hdu['ObjectCat'].data['DEC_OBJ'],
                        objname,
                        hdu['ObjectCat'].data['mag'],
                        hdu['ObjectCat'].data['pBand'],
                        hdu['SlitObjMap'].data['TopDist'][indx],
                        hdu['SlitObjMap'].data['BotDist'][indx]]).T
    #   - Only keep the objects that are in the slit-object mapping
    objects = objects[mapid[indx] == catid]

    # Match the slit IDs in DesiSlits to those in BluSlits
    indx = index_of_x_eq_y(hdu['DesiSlits'].data['dSlitId'], 
                            hdu['BluSlits'].data['dSlitId'],
                            strict=True)

    # PA corresponding to positive x on detector (spatial)
    posx_pa = hdu['MaskDesign'].data['PA_PNT'][-1]
    # Insure it is positive
    posx_pa, _ = positive_maskpa(posx_pa)

    # Instantiate the slit mask object and return it
    try:
        hdu['BluSlits'].data['slitX0']
        indices = numpy.arange(4)
    except KeyError:
        indices = numpy.arange(4)+1
    #indices = numpy.arange(4) if instr == 'keck_deimos' else numpy.arange(4)+1 
    slit_list = []
    for index in indices:
        for cdim in ['X', 'Y']:
            slit_list.append(hdu['BluSlits'].data[f'slit{cdim}{index}'])
    slitmask = SlitMask(numpy.array(slit_list).T.reshape(-1,4,2),
                                slitid=hdu['BluSlits'].data['dSlitId'],
                                align=hdu['DesiSlits'].data['slitTyp'][indx] == 'A',
                                science=hdu['DesiSlits'].data['slitTyp'][indx] == 'P',
                                onsky=numpy.array([hdu['DesiSlits'].data['slitRA'][indx],
                                                hdu['DesiSlits'].data['slitDec'][indx],
                                                hdu['DesiSlits'].data['slitLen'][indx],
                                                hdu['DesiSlits'].data['slitWid'][indx],
                                                hdu['DesiSlits'].data['slitLPA'][indx]]).T,
                                objects=objects,
                                #object_names=hdu['ObjectCat'].data['OBJECT'],
                                mask_radec=(hdu['MaskDesign'].data['RA_PNT'][0], 
                                            hdu['MaskDesign'].data['DEC_PNT'][0]),
                                posx_pa=posx_pa)
    # Return
    return slitmask