Exemple #1
0
    def update_wcs(self, d):
        # d is a dictionary with xshift_best, yshift_best, astr_guess
        # for this EXTNAME

        assert (d['extname'] == self.header['EXTNAME'])

        wcs = d['astr_guess']
        wcs.wcs.crpix = wcs.wcs.crpix + np.array(
            [d['xshift_best'], d['yshift_best']])
        self.wcs = wcs

        # also want to update the header

        new_wcs_header_cards = wcs.to_header()
        new_wcs_header_cards['CONTRAST'] = d['contrast']

        for k, v in new_wcs_header_cards.items():
            if k == 'LATPOLE':
                continue
            self.header[k] = v

        self.header['CD1_1'] = self.header['PC1_1']
        self.header['CD2_1'] = self.header['PC2_1']
        self.header['CD1_2'] = self.header['PC1_2']
        self.header['CD2_2'] = self.header['PC2_2']

        del self.header['PC1_1']
        del self.header['PC2_1']
        del self.header['PC1_2']
        del self.header['PC2_2']
Exemple #2
0
def save_to_fits(img, fits_file, wcs=None, header=None, overwrite=True):
    """Save numpy 2-D arrays to `fits` file. (from `kungpao`)
    Parameters:
        img (np.array, 2d): The 2-D array to be saved
        fits_file (str): File name of `fits` file
        wcs (astropy.wcs.WCS class): World coordinate system of this image
        header (astropy.io.fits.header or str): header of this image
        overwrite (bool): Default is True

    Returns:
        None
    """
    if wcs is not None:
        wcs_header = wcs.to_header()
        img_hdu = fits.PrimaryHDU(img, header=wcs_header)
    else:
        img_hdu = fits.PrimaryHDU(img)

    if header is not None:
        img_hdu.header = header

    if os.path.islink(fits_file):
        os.unlink(fits_file)

    img_hdu.writeto(fits_file, overwrite=overwrite)

    return
Exemple #3
0
    def __init__(self,data,wcs):

        if data.ndim == 3:
            data = np.sum(copy.deepcopy(data),axis=2)
            wcs = pywcs.WCS(wcs.to_header(),naxis=[1,2])
        else:
            data = copy.deepcopy(data)
            
        self._data = data
        self._wcs = wcs
Exemple #4
0
def wcs2hdrdict(wcs, hdr_defaults={}):
    """
    Convert astropy.wcs object into a fits header dictionary

    Note:
        wcs.to_header method annoyingly removes cd_matrix and reset cdelt attributes,
        which is why this functions exists
    """
    import collections
    hdr = collections.OrderedDict()
    hdr['WCSAXES'] = (2, 'Number of World Coordinate System axes')
    hdr['CRPIX1'] = 'Reference pixel for NAXIS1'
    hdr['CRPIX2'] = 'Reference pixel for NAXIS2'
    hdr['CRVAL1'] = '[deg] Coordinate value at reference point'
    hdr['CRVAL2'] = '[deg] Coordinate value at reference point'
    hdr['CTYPE1'] = 'Projection for NAXIS1'
    hdr['CTYPE2'] = 'Projection for NAXIS2'
    hdr['CUNIT1'] = 'Units of coordinate increment and value'
    hdr['CUNIT2'] = 'Units of coordinate increment and value'
    hdr['CROTA2'] = None
    hdr['CD1_1'] = 'Linear projection matrix element'
    hdr['CD1_2'] = 'Linear projection matrix element'
    hdr['CD2_1'] = 'Linear projection matrix element'
    hdr['CD2_2'] = 'Linear projection matrix element'
    hdr.update(hdr_defaults)
    wcs.to_header()
    for k in hdr.keys():
        key = ''.join([ki for ki in k if not ki.isdigit()]).replace('_', '')
        idx = [int(i) - 1 for i in re.sub("\D", "", k)]
        if hasattr(wcs, key.lower()):
            prop = wcs.__getattribute__(key.lower())
            if hasattr(prop, '__len__'):
                for i in idx:
                    prop = prop[i]
            if isinstance(hdr[k], (tuple, list)) and len(hdr[k]) == 2:
                continue
            if isinstance(prop, (int, float)):
                hdr[k] = (prop, hdr[k])
            else:
                hdr[k] = (str(prop), hdr[k])
    return hdr
Exemple #5
0
def make_coadd_map(maps,wcs,shape):
        
    header = wcs.to_header()
    data = np.zeros(shape)
    axes = wcs_to_axes(wcs,shape)
    
    for m in maps:
        c = wcs_to_coords(m.wcs,m.counts.shape)
        o = np.histogramdd(c.T,bins=axes[::-1],weights=np.ravel(m.counts))[0]
        data += o
        
    return Map(data,copy.deepcopy(wcs))
Exemple #6
0
    def toFitsHeader(self):
        """Convert to a FITS header

        Returns
        -------
        header : `astropy.io.fits.Header`
            FITS header with WCS specifying wavelength array.
        """
        wcs = astropy.wcs.WCS(naxis=1)
        wcs.wcs.ctype = ["WAVE"]
        wcs.wcs.cname = ["Wavelength"]
        wcs.wcs.crval = [0.5*(self.minWavelength + self.maxWavelength)]
        wcs.wcs.crpix = [0.5*len(self) + 1.5]  # FITS is unit-indexed
        wcs.wcs.cunit = [astropy.units.nm]
        dWavelength = (self.maxWavelength - self.minWavelength)/(len(self) - 1)
        wcs.wcs.cdelt = [dWavelength]
        return wcs.to_header()
Exemple #7
0
def build_meta(wcs, exif_data):
    time = get_image_time(exif_data)
    wcs.wcs.dateobs = time.isoformat()
    header = MetaDict(dict(wcs.to_header()))

    header.update(get_meta_from_exif(exif_data))
    dsun = sunpy.coordinates.sun.earth_distance(time.isoformat())
    lat = header.get('LAT') * u.deg
    lon = header.get('LON') * u.deg
    solar_rotation_angle = get_solar_rotation_angle(lat, lon, time)
    header.update({'crota2': solar_rotation_angle.to('deg').value})
    header.update({'dsun_obs': dsun.to('m').value})
    hgln_obs = 0 * u.deg
    hglt_obs = sunpy.coordinates.sun.B0(time)
    header.update({'hgln_obs': hgln_obs.to('deg').value})
    header.update({'hglt_obs': hglt_obs.to('deg').value})
    header.update({'ctype1': 'HPLN-TAN'})
    header.update({'ctype2': 'HPLT-TAN'})
    header.update({'rsun': dsun.to('m').value})
    header.update({'rsun_obs': np.arctan(sunpy.sun.constants.radius / dsun).to(
        'arcsec').value})
    return header
Exemple #8
0
def create_frame(background=0, std=100, crpix=None, keys=None):

    size = (100, 100)
    # Update WCS header
    wcs = create_wcs(crpix)
    y, x = numpy.mgrid[:100, :100]

    data = numpy.random.normal(background, std, size)
    model = Gaussian2D(amplitude=30 * background,
                       x_mean=wcs.wcs.crpix[0] - 3.5,
                       y_mean=wcs.wcs.crpix[1] - 12.8,
                       x_stddev=3.0,
                       y_stddev=4.0)
    data += model(x, y)
    hdu = fits.PrimaryHDU(data)

    hdu.header = wcs.to_header()
    if keys:
        for k, v in keys.items():
            hdu.header[k] = v

    return fits.HDUList([hdu])
Exemple #9
0
def create_frame(background=0, std=100, crpix=None, keys=None):

    size = (100, 100)
    # Update WCS header
    wcs = create_wcs(crpix)
    y, x = numpy.mgrid[:100, :100]

    data = numpy.random.normal(background, std, size)
    model = Gaussian2D(
        amplitude=30*background,
        x_mean=wcs.wcs.crpix[0]-3.5,
        y_mean=wcs.wcs.crpix[1]-12.8,
        x_stddev=3.0,
        y_stddev=4.0
    )
    data += model(x, y)
    hdu = fits.PrimaryHDU(data)

    hdu.header = wcs.to_header()
    if keys:
        for k, v in keys.items():
            hdu.header[k] = v

    return fits.HDUList([hdu])
Exemple #10
0
    def _args_to_payload(self, **kwargs):
        # Convert arguments to a valid requests payload
        # Build the payload
        payload = {}

        # If a wcs is still present in the kwargs it means
        # the user called query_with_wcs
        if kwargs.get('wcs'):
            wcs = kwargs.pop('wcs')
            header = wcs.to_header()

            # hips2fits needs the size of the output image
            if wcs.pixel_shape is not None:
                nx, ny = wcs.pixel_shape
                header['NAXIS1'] = nx
                header['NAXIS2'] = ny
            else:
                # The wcs does not contain the size of the image
                raise AttributeError("""The WCS passed does not contain the size of the pixel image.
                Please add it to the WCS or refer to the query method.""")

            # Add the WCS to the payload
            header_json = dict(header.items())
            header_str = json.dumps(header_json)
            payload.update({'wcs': header_str})
        else:
        # The user called query
            payload.update({
                'width': kwargs.pop("width"),
                'height': kwargs.pop("height"),
                'projection': kwargs.pop("projection"),
                'coordsys': kwargs.pop("coordsys"),
                'rotation_angle': kwargs.pop("rotation_angle").to_value(u.deg),
                'ra': kwargs.pop("ra").to_value(u.deg),
                'dec': kwargs.pop("dec").to_value(u.deg),
                'fov': kwargs.pop("fov").to_value(u.deg),
            })

        # Min-cut
        min_cut_value = kwargs.pop('min_cut')
        min_cut_kw = str(min_cut_value) + '%'
        payload.update({'min_cut': min_cut_kw})

        # Max-cut
        max_cut_value = kwargs.pop('max_cut')
        max_cut_kw = str(max_cut_value) + '%'
        payload.update({'max_cut': max_cut_kw})

        # Colormap
        cmap = kwargs.pop('cmap')
        from matplotlib.colors import Colormap
        if isinstance(cmap, Colormap):
            cmap = cmap.name
        payload.update({'cmap': cmap})

        # Stretch
        stretch = kwargs.pop('stretch')
        # TODO remove that: it must be handled properly by the server side
        # that should return a json error
        if stretch not in ('power', 'linear', 'sqrt', 'log', 'asinh'):
            msg = "stretch: must either 'power', 'linear', 'sqrt', 'log' or 'asinh'.\n"
            msg += str(stretch) + ' is ignored.'

            warnings.warn(msg, AstropyUserWarning)
        else:
            payload.update({'stretch': stretch})
        payload.update({'stretch': stretch})

        # HiPS
        hips = kwargs.pop("hips")
        # Output format
        format = kwargs.pop("format")
        payload.update({
            "hips": hips,
            "format": format,
        })

        # Check that all the arguments have been handled
        assert kwargs == {}

        return payload
Exemple #11
0
def make_maps(coords: SkyCoord,
              ext: ExtinctionCatalogue,
              wcs: astropy.wcs.WCS,
              kde: KDE,
              n_iters: int = 3,
              tolerance: float = 3.0,
              use_xnicest: bool = True):
    """Map making algorithm.

    Parameters
    ----------
    coords : SkyCoord
        The coordinates of all objects. Not all objects might have measured
        extinctions, so the size of this catalogue is generally larger than
        the one of `ext`.

    ext : ExtinctionCatalogue
        An extinction catalogue for the valid objects. Note that we use the
        `idx` attribute of the catalogue to select only valid objects in the
        coords.

    wcs : WCS
        A Worlk Coordinate System structure, returned for example by
        `guess_wcs`.

    kde : KDE
        A KDE object, the kernel density estimator that will be used to build
        smooth maps.

    n_iters : int, default to 3
        The number of iterations performed. At the end of each iteration,
        unusual objects are clipped. Clipping does not occur if n_iters = 1.

    tolerance : float, default to 3.0
        The maximum tolerance allowed in the extinction of each object.
        Objects that have an extinction that differs the local extinction by
        more than `tolerance` times the local standard deviation will be
        excluded from the analysis. This requires several passes or
        iterations, as dictated by the `n_iters` argument.

    use_xnicest : bool, default to True
        If False, the XNicest algorithm will not be used, not even if the
        `ext` catalogue has XNicest weights computed.

    Returns
    -------
    fits.HDU
        A full HDU fits structure, which can be used directly to save a FITS
        file. Alternatively, one can use the `data` attribute of the result to
        obtain directly the various maps created. The `data` attribute is a 3D
        array: each "plane" contains different results:

        data[0]
            The XNicer extinction map, in units of [mag].

        data[1]
            The inverse variance on the XNicer extinction map [mag^-2]. One
            can obtains the error of the extinction map by computing
            data[1]**(-0.5)

        data[2]
            The sum of weights of the extinction map [mag^-2 pix^-1]. This is
            mostly provided for sanity checks: pixels with a small value in
            data[2] indicate places where few objects are observed, or places
            where objects have large extinction measurement errors.

        data[3]
            The local density of objects, in units of [objects pix^-1].

        data[4]
            The XNicest extinction map [mag]. Only returned if the XNicest
            algorithm has been used.

        data[5]
            The inverse variance on the XNicest extinction map [mag^-2]. Only
            returned if the XNicest algorithm has been used.

        data[6]
            The sum of weights of the XNIcest extinction map [mag^-2 pix^-1].
            Only returned if the XNicest algorithm has been used.

    """
    names = list(coords.frame.representation_component_names.keys())
    if 'idx' in ext.colnames:
        xy = wcs.all_world2pix(
            getattr(coords, names[0]).deg[ext['idx']],
            getattr(coords, names[1]).deg[ext['idx']], 0)
    else:
        xy = wcs.all_world2pix(
            getattr(coords, names[0]).deg,
            getattr(coords, names[1]).deg, 0)
    xy = np.stack((xy[1], xy[0]), axis=-1)
    mask = kde.mask_inside(xy)
    n_objs = xy.shape[0]
    # Check if we need to use the XNicest algorithm
    xnicest = bool(use_xnicest) and ('xnicest_bias' in ext.colnames)
    # Weights & power arrays: 0-cmap, 1-cvar, 2-cwgt, 3-dmap
    # Moreover, if xnicest: 4-amap, 5-avar, 6-awgt
    if xnicest:
        weights = np.empty((7, n_objs))
        power = np.zeros(7)
    else:
        weights = np.empty((4, n_objs))
        power = np.zeros(4)
    ext_ivar = 1.0 / ext['variance_A']
    weights[0, :] = ext['mean_A'] * ext_ivar
    weights[1, :] = ext['mean_A'] * ext['mean_A'] * ext_ivar
    weights[2, :] = ext_ivar
    weights[3, :] = 1
    if xnicest:
        weights[4, :] = (ext['mean_A'] - ext['xnicest_bias']) * ext_ivar * \
            ext['xnicest_weight']
        # FIXME: The following line, used to compute the XNicest error,
        # ignores the error on the xnicest_weight. That is, the final error
        # will be computed by assuming only the error on the extinction. The
        # issue is not so easy to solve (one would need to take into account
        # both the variance on the XNicest weight and the covariance with the
        # extinction). For a further release...
        weights[5, :] = ext_ivar * ext['xnicest_weight']
        power[5] = 1
        weights[6, :] = ext_ivar * ext['xnicest_weight']
    # Shifted (unframed) coordinates, to the nearest int
    x_ = np.rint(xy[:, 1] + kde.kernel_size).astype(np.int)
    y_ = np.rint(xy[:, 0] + kde.kernel_size).astype(np.int)
    for iteration in range(n_iters):
        if iteration < n_iters - 1:
            # Faster steps for intermediate iterations
            res = kde.kde(xy,
                          weights[0:3],
                          power=power[0:3],
                          mask=mask,
                          nocut=True)
        else:
            # Last iteration is complete; also, change the weights and power
            # for the map #1, so that it measures the expected variance,
            # instead of the observed one.
            weights[1] = weights[2]
            power[1] = 1
            res = kde.kde(xy, weights, power=power, mask=mask, nocut=True)
        res[0] = np.divide(res[0],
                           res[2],
                           out=np.zeros_like(res[0]),
                           where=(res[2] != 0))
        if iteration < n_iters - 1:
            # Intermediate iterations: cvar is the observed scatter and has to
            # be computed as a sampled variance
            res[1] = np.divide(res[1],
                               res[2],
                               out=np.zeros_like(res[1]),
                               where=(res[2] != 0))
            res[1] -= res[0]**2
            # Intermediate iterations: update the mask
            x_mask = x_[mask]
            y_mask = y_[mask]
            clip = (res[0, y_mask, x_mask] - ext['mean_A'][mask])** 2 \
                > tolerance**2 * res[1, y_mask, x_mask]
            mask[np.where(mask)[0][clip]] = False
        else:
            # Last iteration: cvar is the ensemble variance
            res[1] = np.divide(res[2] * res[2],
                               res[1],
                               out=np.zeros_like(res[1]),
                               where=(res[1] != 0))
            if xnicest:
                # Last iteration: compute the other intermediate maps
                res[4] = np.divide(res[4],
                                   res[6],
                                   out=np.zeros_like(res[4]),
                                   where=(res[4] != 0))
                res[5] = np.divide(res[6] * res[6],
                                   res[5],
                                   out=np.zeros_like(res[5]),
                                   where=(res[5] != 0))
    # Cut the data
    res = res[:, kde.kernel_size:-kde.kernel_size,  # type: ignore
              kde.kernel_size:-kde.kernel_size]
    # Prepare the header
    hdu = fits.PrimaryHDU(res, header=wcs.to_header())
    hdu.header['PLANE1'] = ('extinction', '[mag]')
    hdu.header['PLANE2'] = ('inverse variance', '[mag^-2]')
    hdu.header['PLANE3'] = ('weight', '[mag^-2 pix^-1]')
    hdu.header['PLANE4'] = ('density', '[pix^-1], objects per pixel')
    if xnicest:
        hdu.header['PLANE5'] = ('extinction', '[mag], XNicest method')
        hdu.header['PLANE6'] = ('inverse variance', '[mag^-2], XNicest method')
        hdu.header['PLANE7'] = ('weight', '[mag^2 pix^-1], XNicest method')
    hdu.header['CREATOR'] = 'XNicer v0.2.0'
    hdu.header['DATE'] = datetime.datetime.now().isoformat()
    hdu.header['AUTHOR'] = 'Marco Lombardi'
    hdu.add_checksum()
    # All done: return the final maps, truncated
    return hdu
Exemple #12
0
def write_fits_image(data,wcs,outfile):
    
    hdu_image = pyfits.PrimaryHDU(data,header=wcs.to_header())
#        hdulist = pyfits.HDUList([hdu_image,h['GTI'],h['EBOUNDS']])
    hdulist = pyfits.HDUList([hdu_image])        
    hdulist.writeto(outfile,clobber=True)    
Exemple #13
0
 def macro(self, exposure: Exposure, context: Dict[str, Any] = {}):
     if exposure.wcs is None:
         wcs = astropy.wcs.WCS()
     else:
         wcs = exposure.wcs
     return list(wcs.to_header().cards)
Exemple #14
0
def _dump_fits(filename, data, wcs, overwrite=False):
    fits.writeto(
        filename, data, header=wcs.to_header(),
        output_verify='exception', overwrite=overwrite, checksum=True)