def sky_offset(self, ra_offset, dec_offset): """ Update header keywords to simulate a shift in telescope pointing. Parameters ---------- ra_offset: float Shift in RA (arcseconds) dec_offset: float Shift in declination (arcseconds) """ self.phu['RAOFFSET'] += ra_offset self.phu['DECOFFSE'] += dec_offset # XOFFSET, YOFFSET xoffset, yoffset = self._xymapping(ra_offset, dec_offset) self.phu['XOFFSET'] += xoffset self.phu['YOFFSET'] += yoffset # POFFSET. QOFFSET poffset, qoffset = self._pqmapping(ra_offset, dec_offset) self.phu['POFFSET'] += poffset self.phu['QOFFSET'] += qoffset # WCS matrix for ext in self: ext.hdr['CRVAL1'] += ra_offset / (3600. * cosd(self.dec())) ext.hdr['CRVAL2'] += dec_offset / 3600. ext.wcs = adwcs.fitswcs_to_gwcs(ext.hdr)
def rotate(self, angle): """ Modify the CD matrices of all the headers to effect a rotation. This assumes that the CRVALi keywords are the same in all headers or else this modification may be inconsistent. Parameters ---------- angle: float Rotation angle (degrees) """ for ext in self: cd_matrix = models.Rotation2D(angle)(*WCS(ext.hdr).wcs.cd) ext.hdr.update({ 'CD{}_{}'.format(i + 1, j + 1): cd_matrix[i][j] for i in (0, 1) for j in (0, 1) }) ext.wcs = adwcs.fitswcs_to_gwcs(ext.hdr) self.phu['PA'] = (self.phu.get('PA', 0) + angle) % 360
def add_extension(self, data=None, shape=None, dtype=np.float32, pixel_scale=None, flip=False, extra_keywords={}): """ Add an extension to the existing AD, with some basic header keywords. Parameters ---------- data: array/None data to add; if None, add zeros of specified shape shape: tuple/None dimensions of .data plane; if None, will use the shape of the first extension (ignored if data is not None) dtype: datatype datatype of data if data is None pixel_scale: float/None pixel scale for this plane; if None, use the descriptor value flip: bool if True, flip the WCS (so East is to the right if North is up) extra_keywords: dict extra keywords to put in this extension's Header """ # If no shape is provided, use the first extension's shape if data is None: if shape is None and len(self) > 0: shape = self[0].nddata.shape elif shape is None: raise ValueError("Must specify a shape if data is None") self.append(np.zeros(shape, dtype=dtype)) else: self.append(data) shape = data.shape extver = len(self) shape_value = '[1:{1},1:{0}]'.format(*shape) self[-1].hdr.update({ 'EXTNAME': 'SCI', 'EXTVER': extver, self._keyword_for('data_section'): shape_value, self._keyword_for('detector_section'): shape_value, self._keyword_for('array_section'): shape_value }) self[-1].hdr.update(extra_keywords) # For instruments with multiple extensions, the relationship between # the WCS keywords on the extenstions has to be handled at the # instrument level. Here we just deal with the case of creating the # first extension and put the fiducial point in the middle. if len(self) == 1 and 'RA' in self.phu and 'DEC' in self.phu: self[-1].hdr.update({ 'CRVAL1': self.phu['RA'], 'CRVAL2': self.phu['DEC'], 'CTYPE1': 'RA---TAN', 'CTYPE2': 'DEC--TAN', 'CRPIX1': 0.5 * (shape[-1] + 1), 'CRPIX2': 0.5 * (shape[-2] + 1) }) if pixel_scale is None: pixel_scale = self.pixel_scale() pa = self.phu.get('PA', 0) if pixel_scale is not None: cd_matrix = models.Rotation2D(angle=pa)( *np.array([[pixel_scale if flip else -pixel_scale, 0], [0, pixel_scale]]) / 3600.0) self[-1].hdr.update({ 'CD{}_{}'.format(i + 1, j + 1): cd_matrix[i][j] for i in (0, 1) for j in (0, 1) }) self[-1].wcs = adwcs.fitswcs_to_gwcs(self[-1].hdr)