Ejemplo n.º 1
0
    def _calculateSkyCoords(self):
        """
        Calculates sky coordinates for the slits.
        Resamples the direct image pixels back to the
        slit image pixels. Takes the average in x-direction
        which is assumed to be across the slit, so that
        the sky coordinates are at the centre of the slit
        in this direction.
        """
        #calculate the RA and DEC of the centre of the centre slit
        centre = np.array([[self.result['xcenter'], self.result['ycenter']], ], np.float_)
        sky = self.result['WCS'].wcs_pix2sky(centre, 1)
        self.result['RA'] = sky[0][0]
        self.result['DEC'] = sky[0][1]

        #each slit pixels
        for key, value in self.slits.items():
            ymin = value['ymin'] + self.result['y']
            ymax = value['ymax'] + self.result['y']
            y = np.arange(ymin, ymax)
            #y is now sampled to the supersampled direct image
            #what we ultimately need is the coordinates
            #for slit pixels...
            resample = value['pixels']
            ybin = m.frebin(y, resample)

            #for x, given that it is the slit width
            #we need the mean value
            xmin = value['xmin'] + self.result['x']
            xmax = value['xmax'] + self.result['x']
            mean = np.mean(np.array([xmin, xmax]))
            #x = np.zeros(len(y)) + mean
            xbin = np.zeros(len(ybin)) + mean

            pixels = []
            for a, b in zip(xbin, ybin):
                pixels.append([a, b])
            pixels = np.asanyarray(pixels)
            sky = self.result['WCS'].wcs_pix2sky(pixels, 1)
            #sky = self.result['WCS'].toworld(pixels)

            self.slits[key]['coordinates'] = sky

            #record x and y in the slit frame
            self.slits[key]['coordinatesXY'] = pixels
            self.slits[key]['coordinatesX'] = np.ones(value['pixels'])
            self.slits[key]['coordinatesY'] = np.arange(value['pixels']) + 1

            #RA and DEC of the centre of the slit
            centre = np.array([[mean, (ymax + ymin) / 2.], ])
            sky = self.result['WCS'].wcs_pix2sky(centre, 1)
            self.slits[key]['RA'] = sky[0][0]
            self.slits[key]['DEC'] = sky[0][1]

            if self.debug:
                print self.slits[key]['RA'], self.slits[key]['DEC']
Ejemplo n.º 2
0
    def _calculateDifference(self):
        """
        Calculates the difference between the derived observed and SDSS spectra.

        Interpolates the SDSS spectra to the same wavelength scale.

        .. Warning:: We do not conserve flux here when interpolating. This is because
                     we do not actually interpolate flux but flux density which is per
                     angstrom.
        """
        ms = (self.fitting['SDSSwave'] >= np.min(self.fitting['obsWavelengths'])) &\
             (self.fitting['SDSSwave'] <= np.max(self.fitting['obsWavelengths']))
        newflux = m.frebin(self.fitting['SDSSflux'][ms],    
                           len(self.fitting['obsSpectraConvolved']))#, total=True)

        self.fitting['spectraRatio'] = self.fitting['obsSpectraConvolved'] / newflux
        self.fitting['interpFlux'] = newflux
Ejemplo n.º 3
0
    def _calculateDifference(self):
        """
        Calculates the difference between the derived observed and SDSS spectra.

        Interpolates the SDSS spectra to the same wavelength scale.

        .. Warning:: We do not conserve flux here when interpolating. This is because
                     we do not actually interpolate flux but flux density which is per
                     angstrom.
        """
        ms = (self.fitting['SDSSwave'] >= np.min(self.fitting['obsWavelengths'])) &\
             (self.fitting['SDSSwave'] <= np.max(self.fitting['obsWavelengths']))
        newflux = m.frebin(
            self.fitting['SDSSflux'][ms],
            len(self.fitting['obsSpectraConvolved']))  #, total=True)

        self.fitting[
            'spectraRatio'] = self.fitting['obsSpectraConvolved'] / newflux
        self.fitting['interpFlux'] = newflux
Ejemplo n.º 4
0
def hrebin(imagefile, newx, newy, output='rebinned.fits', ext=0, total=False):
    """
    Expand or contract a FITS image and update the header.
    Based on IDL routine hrebin.pro, but removed some functionality

    :todo: remove the pywcs dependency

    :param imagefile: name of the FITS file to be rebinned
    :param newx:  size of the new image in the X direction, integer scalar
    :param newy: size of the new image in the Y direction, integer scalar
    :param output: Name of the outputfile or None
    :param ext: the FITS extension of the header and data

    :return: None or updated img and hdr
    """
    #todo: remove the pywcs dependency
    #todo: add a routine for exact rebinning, now done with the same
    fh = pf.open(imagefile)
    oldhdr = fh[ext].header
    oldimg = fh[ext].data
    fh.close()

    wcs = pywcs.WCS(oldhdr)

    #old size
    #xsize = oldhdr['NAXIS1']
    #ysize = oldhdr['NAXIS2']
    ysize, xsize = oldimg.shape

    #ratios
    xratio = newx / float(xsize)
    yratio = newy / float(ysize)
    #change in the aspect ratio
    lambd = yratio / xratio
    #Ratio of pixel areas
    pix_ratio = xratio * yratio

    #chech whether the new size is an exact match
    exact = (xsize % newx == 0) | (newx % xsize == 0) and\
            (ysize % newy == 0) | (newy % ysize == 0)

    #rebin based on whether the rebinning is exact or not
    if exact:
        oldimg = manipulate.frebin(oldimg, newx, newy, total=total)
    else:
        oldimg = manipulate.frebin(oldimg, newx, newy, total=total)

    #start updating the new header
    oldhdr['NAXIS1'] = int(newx)
    oldhdr['NAXIS2'] = int(newy)
    #add comment orig size and new size
    oldhdr.add_comment('rebinned: original image was %i by %i' %
                       (xsize, ysize))

    #Correct the position of the reference pixel.
    #Note that CRPIX values are given in FORTRAN (first pixel is (1,1)) convention
    crpix = wcs.wcs.crpix

    #update astrometry
    if exact and xratio > 1:
        crpix1 = (crpix[0] - 1.0) * xratio + 1.0
    else:
        crpix1 = (crpix[0] - 0.5) * xratio + 0.5

    if exact and yratio > 1:
        crpix2 = (crpix[1] - 1.0) * yratio + 1.0
    else:
        crpix2 = (crpix[1] - 0.5) * yratio + 0.5

    oldhdr['CRPIX1'] = crpix1
    oldhdr['CRPIX2'] = crpix2

    #distortion correction, not implemented
    #oldhdr['CDELT1'] /= xratio
    #oldhdr['CDELT2'] /= yratio

    oldhdr['CD1_1'] /= xratio
    oldhdr['CD1_2'] /= yratio
    oldhdr['CD2_1'] /= xratio
    oldhdr['CD2_2'] /= yratio

    #modify the B scale
    #oldhdr['BSCALE'] /= pix_ratio

    #write out a new FITS file
    hdu = pf.PrimaryHDU(oldimg)
    hdu.header = oldhdr
    hdu.header.add_history(
        'Updated: %s' % datetime.datetime.isoformat(datetime.datetime.now()))
    if os.path.isfile(output):
        os.remove(output)
    hdu.writeto(output)

    return oldimg, oldhdr
Ejemplo n.º 5
0
def hrebin(imagefile, newx, newy, output='rebinned.fits', ext=0, total=False):
    """
    Expand or contract a FITS image and update the header.
    Based on IDL routine hrebin.pro, but removed some functionality

    :todo: remove the pywcs dependency

    :param imagefile: name of the FITS file to be rebinned
    :param newx:  size of the new image in the X direction, integer scalar
    :param newy: size of the new image in the Y direction, integer scalar
    :param output: Name of the outputfile or None
    :param ext: the FITS extension of the header and data

    :return: None or updated img and hdr
    """
    #todo: remove the pywcs dependency
    #todo: add a routine for exact rebinning, now done with the same
    fh = pf.open(imagefile)
    oldhdr = fh[ext].header
    oldimg = fh[ext].data
    fh.close()

    wcs = pywcs.WCS(oldhdr)

    #old size
    #xsize = oldhdr['NAXIS1']
    #ysize = oldhdr['NAXIS2']
    ysize, xsize = oldimg.shape

    #ratios
    xratio = newx / float(xsize)
    yratio = newy / float(ysize)
    #change in the aspect ratio
    lambd = yratio / xratio
    #Ratio of pixel areas
    pix_ratio = xratio * yratio

    #chech whether the new size is an exact match
    exact = (xsize % newx == 0) | (newx % xsize == 0) and\
            (ysize % newy == 0) | (newy % ysize == 0)

    #rebin based on whether the rebinning is exact or not
    if exact:
        oldimg = manipulate.frebin(oldimg, newx, newy, total=total)
    else:
        oldimg = manipulate.frebin(oldimg, newx, newy, total=total)

    #start updating the new header
    oldhdr['NAXIS1'] = int(newx)
    oldhdr['NAXIS2'] = int(newy)
    #add comment orig size and new size
    oldhdr.add_comment('rebinned: original image was %i by %i' % (xsize, ysize))

    #Correct the position of the reference pixel.
    #Note that CRPIX values are given in FORTRAN (first pixel is (1,1)) convention
    crpix = wcs.wcs.crpix

    #update astrometry
    if exact and xratio > 1:
        crpix1 = (crpix[0] - 1.0) * xratio + 1.0
    else:
        crpix1 = (crpix[0] - 0.5) * xratio + 0.5

    if exact and yratio > 1:
        crpix2 = (crpix[1] - 1.0) * yratio + 1.0
    else:
        crpix2 = (crpix[1] - 0.5) * yratio + 0.5

    oldhdr['CRPIX1'] = crpix1
    oldhdr['CRPIX2'] = crpix2

    #distortion correction, not implemented
    #oldhdr['CDELT1'] /= xratio
    #oldhdr['CDELT2'] /= yratio

    oldhdr['CD1_1'] /= xratio
    oldhdr['CD1_2'] /= yratio
    oldhdr['CD2_1'] /= xratio
    oldhdr['CD2_2'] /= yratio

    #modify the B scale
    #oldhdr['BSCALE'] /= pix_ratio

    #write out a new FITS file
    hdu = pf.PrimaryHDU(oldimg)
    hdu.header = oldhdr
    hdu.header.add_history('Updated: %s' % datetime.datetime.isoformat(datetime.datetime.now()))
    if os.path.isfile(output):
        os.remove(output)
    hdu.writeto(output)

    return oldimg, oldhdr
Ejemplo n.º 6
0
    def _fitSlitsToDirectImage(self):
        """
        Fits a slit mask profiles to a direct image to recover the position and orientation of the slitmask.

        By default the counts are not normalized to a peak count, but this can
        be controlled using the optional keyword normalize. This should be used for
        debugging purposes only. I included this part because in the beginning we
        were missing flux calibration.

        :Note: This is a very slow algorithm because of the insanely many nested for loops...

        :todo: rewrite the algorithm.

        :rtype: dictionary
        """
        #generates a model array from the slit values, takes into account potential
        #throughput of a slit
        model = np.array([])
        for vals in self.slits.values():
            #must rebin/interpolate to the right scale, conserve surface flux
            new = m.frebin(vals['profile'], int(vals['height']), total=True)
            model = np.append(model, new)
            self.fitting[vals['file']] = new

        if self.normalize:
            model /= np.max(model)

        #mask out negative values and especially those equal to zero
        msk = model > 0.0
        self.fitting['model'] = model[msk]
        self.fitting['mask'] = msk

        #basic model information
        mean = np.mean(self.fitting['model'])
        sig = np.sqrt(np.sum((self.fitting['model'] - mean) ** 2))
        diff = self.fitting['model'] - mean
        self.fitting['sig'] = sig
        self.fitting['diff'] = diff

        #generate rotations
        if self.rotation:
            rotations = np.arange(-self.fitting['rotation'], self.fitting['rotation'], self.fitting['rotstep'])
            rotations[(rotations < 1e-8) & (rotations > -1e-8)] = 0.0
            #make a copy of the direct image
            origimage = self.direct['rotatedImage'].copy()
        else:
            rotations = [0, ]

        #x and yranges to cover in the grid
        xran = range(-self.fitting['xrange'], self.fitting['xrange'], self.fitting['xstep'])
        yran = range(-self.fitting['yrange'], self.fitting['yrange'], self.fitting['ystep'])

        #define some helper variables
        out = []
        corrmin = -1e10
        cm = 1e30

        #loop over a range of rotations, x and y positions
        #this should be done in some other way than having three nested loops... not good
        for r in rotations:
            if self.rotation:
                if r != 0.0:
                    #d = interpolation.rotate(origimage, r, reshape=False)
                    d, hdrR = modify.hrot2(origimage.copy(), self.direct['rotatedHeader'], r, xc=None, yc=None)
                else:
                    d = origimage.copy()
                    hdrR = self.direct['rotatedHeader']
            else:
                d = self.direct['rotatedImage'].copy()
                hdrR = self.direct['rotatedHeader']

            #only for debugging purposes
            if self.normalize:
                d /= np.max(d)

            for x in xran:
                for y in yran:
                    #all slits
                    dirdata = np.array([])
                    for s in self.slits.values():
                        #direct image data
                        dirdat = d[s['ymin'] + y:s['ymax'] + y,\
                                   s['xmin'] + x:s['xmax'] + x]
                        #sum the counts inside the slit
                        dirdat = np.sum(dirdat, axis=1)
                        dirdata = np.append(dirdata, dirdat.ravel())

                    #remove the masked pixels
                    dirdata = dirdata[self.fitting['mask']]

                    #chi**2, p-value
                    chisq = stats.chisquare(dirdata, self.fitting['model'])
                    #chisq = self._chiSquare(dirdata, self.fitting['model'], 1./self.fitting['model'])

                    #correlation coeff
                    mean = np.mean(dirdata)
                    sig = np.sqrt(np.sum((dirdata - mean) ** 2))
                    diff = dirdata - mean
                    corr = np.sum(self.fitting['diff'] * diff) / self.fitting['sig'] / sig

                    #save info
                    tmp = [r, x, y, chisq[0], chisq[0] / s['pixels'], chisq[1], corr]
                    #tmp = [r, x, y, chisq, chisq / s['pixels'], 0.0, corr]
                    out.append(tmp)

                    if chisq[0] < cm:
                    #if chisq < cm:
                        cm = chisq[0]
                        #cm = chisq
                        minpos = tmp
                        dir = dirdata
                        img = d
                        hdr = hdrR

                    if corr > corrmin:
                        corrmin = corr
                        minpos2 = tmp
                        dir2 = dirdata

                    if self.debug:
                        print r, x, y, chisq[0] / s['pixels'], chisq[1], corr
                        #print r, x, y, chisq / s['pixels'], 0.0, corr

        #save results
        self.result['outputs'] = out
        self.result['minimaPosition'] = minpos
        self.result['FinalImage'] = img
        self.result['FinalHeader'] = hdr
        self.result['WCS'] = pywcs.WCS(hdr)
        #self.result['WCS'] = wcs.Projection(hdr)
        #choose the method
        if 'chi' in self.fitting['method']:
            self.result['rotation'] = minpos[0]
            self.result['posangle'] = minpos[0] + self.slits[self.centralFile]['POSANGLE']
            self.result['x'] = minpos[1]
            self.result['y'] = minpos[2]
            self.result['bestfit'] = dir
            self.result['xcenter'] = self.direct['xposition'] + minpos[1]
            self.result['ycenter'] = self.direct['yposition'] + minpos[2]
            self.result['pvalue'] = minpos[5]
        elif 'corr' in self.fitting['method']:
            self.result['rotation'] = minpos2[0]
            self.result['posangle'] = minpos[0] + self.slits[self.centralFile]['POSANGLE']
            self.result['x'] = minpos2[1]
            self.result['y'] = minpos2[2]
            self.result['bestfit'] = dir2
            self.result['xcenter'] = self.direct['xposition'] + minpos2[1]
            self.result['ycenter'] = self.direct['yposition'] + minpos2[2]
            self.result['pvalue'] = minpos2[5]
        else:
            raise NotImplementedError, 'This minimization method has not yet been implemented...'

        if self.debug:
            print minpos
            print minpos2