Beispiel #1
0
def matchprob(x, w, f, xp, xf, sl, ws, dw=5):
    """Calculate the probability that the line is the correct match.
       If it is matched up correctly and the solution is correct, then the
       other lines should be found in the right place.   The probabilibty will
       decrease by a factor of 0.1 for each line not found in the right place.
    """
    if w == -1:
        return 0
    p = 1.0
    # first assume that the zero point of the solution is set by the value
    try:
        nws = copy.deepcopy(ws)
    except:
        nws = WavelengthSolution.WavelengthSolution(
            ws.x_arr, ws.w_arr, ws.function, ws.order, 
            domain=ws.func.func.domain)
        nws.fit()
    nws.coef[0] = nws.coef[0] - (nws.value(x) - w)

    # Now loop through and see how well other objects end up fitting
    # if they are not present or there is problems, reduce the probability
    for i in xf.argsort()[::-1]:
        dist = abs(sl - nws.value(xp[i]))
        if dist.min() > dw:
            p = p * (1 - 0.1)
        else:
            p = p * (1 - 0.1 * dist.min() / dw * xf[i] / xf.max())
        # print x, w, xp[i], nws.value(xp[i]),sl[dist.argmin()],xf[i],
        # dist.min(),p

    return p
Beispiel #2
0
def findwavelengthsolution(xarr, farr, sl, sf, ws, mdiff=20, wdiff=20, sigma=5,
                           niter=5):
    """Calculates the wavelength solution given a spectra and a set of lines.
       Hopefully an accurate first guess (ws) is provided and relative fluxes
       are provided as well, but if not, then the program is still designed
       to attempt to handle it.

       returns ws
    """
    # match up the features
    # xp, wp=findfeatures(xarr, farr, sl, sf, ws, mdiff=mdiff, wdiff=wdiff,
    #                    sigma=sigma, niter=niter)
    xp, wp = crosslinematch(xarr, farr, sl, sf, ws, mdiff=mdiff, wdiff=wdiff,
                            sigma=sigma, niter=niter)

    # find the solution to the best fit
    mask = (wp > 0)
    if mask.sum() >= ws.order:
        nws = WavelengthSolution.WavelengthSolution(
            xp[mask], wp[mask], order=ws.order, function=ws.function, 
            domain = ws.func.func.domain)
        nws.fit()
    else:
        nws = None
    # for i in range(len(xp)): print xp[i], wp[i], wp[i]-nws.value(xp[i])
    # print nws.sigma(xp,wp)
    return nws
Beispiel #3
0
def findfit(xp, wp, ws=None, **kwargs):
    """Find the fit using just the matched points of xp and wp"""
    if ws is None:
        ws = WavelengthSolution.WavelengthSolution(xp, wp, **kwargs)
    else:
        ws.set_array(xp, wp)
        ws.set_func(domain = ws.func.func.domain)
    if len(xp) < ws.order:
        msg = 'Not enough points to determine an accurate fit'
        raise SALTSpecError(msg)
    ws.fit()
    return ws
Beispiel #4
0
def fitxcor(xarr, farr, swarr, sfarr, ws, interptype='interp', method='Nelder-Mead'):
    """Maximize the normalized cross correlation coefficient for the full
        wavelength solution
    """
    try:
        nws = copy.deepcopy(ws)
    except:
        nws = WavelengthSolution.WavelengthSolution(
            ws.x_arr, ws.w_arr, ws.function, ws.order)
        nws.coef.set_coef(ws.coef)

    res = minimize(xcorfun, nws.coef, method=method,
                   args=(xarr, farr, swarr, sfarr, interptype, nws))
    bcoef = res['x']
    nws.set_coef(bcoef)
    return nws
Beispiel #5
0
def findsol(xarr, soldict, y_i, caltype, nearest, timeobs, exptime, instrume, grating, grang, arang, filtername,
            slit, xbin, ybin, slitid, function, order):
    """Find the wavelength solution.  Either from a database containing all the
       solutions adn calculate the best one or calculate based on the model
       for RSS
    """

    if caltype == 'line':
        function, order, coef, domain = findlinesol(
            soldict, y_i, nearest, timeobs, exptime, instrume, grating, grang, arang, filtername, slitid, xarr)
        if function is None:
            msg = 'No solution matches for %s, %s, %s, %s, %s, %s' % (
                instrume, grating, grang, arang, filtername, slitid)
            raise SALTSpecError(msg)
        if coef is None:
            return None
        order = int(order)
        ws = WavelengthSolution.WavelengthSolution(
            xarr,
            xarr,
            function=function,
            order=order) 
        ws.func.func.domain = domain
        ws.set_coef(coef)
        w_arr = ws.value(xarr)

    elif caltype == 'rss':
        w_arr = calcsol(
            xarr,
            y_i,
            instrume,
            grating,
            grang,
            arang,
            filtername,
            slit,
            xbin,
            ybin,
            function,
            order)
    else:
        message = 'SALTRECTIFY--Invalid caltype'
        raise SALTSpecError(message)

    return w_arr
Beispiel #6
0
def findlinesol(soldict, yc, nearest, timeobs, exptime,
                instrume, grating, grang, arang, filtername, slitid, xarr=None):
    """Find the best wavelength solution given a datetime of the observation
       and a wavelenght line.  We will assume that the best solution is found
       between the two solutions which are on either side of the timeobs or
       otherwise the closest time.

    """

    # if there is only one return that one
    if len(soldict) == 1:
        sol = soldict.keys()[0]
        function = soldict[sol][7]
        order = soldict[sol][8]
        coef = findcoef(yc, soldict[sol][9], soldict[sol][10])
        domain = soldict[sol][11]
        return function, order, coef, domain

    # first find the closest wavelength solution in time and use that for
    # a base sample
    time_list = []
    function_list = []
    order_list = []
    domain_list = []
    coef_list = []
    for sol in soldict:
        if matchobservations(
                soldict[sol], instrume, grating, grang, arang, filtername, slitid):
            # right at the same time
            if (soldict[sol][0] - timeobs).seconds == 0.0:
                function = soldict[sol][7]
                order = soldict[sol][8]
                coef = findcoef(yc, soldict[sol][9], soldict[sol][10])
                domain = soldict[sol][11]
                return function, order, coef, domain
            else:
                t = timeobs + datetime.timedelta(seconds=exptime)
                time_list.append(subtracttime(soldict[sol][0], t))
                function_list.append(soldict[sol][7])
                order_list.append(soldict[sol][8])
                domain_list.append(soldict[sol][11])
                coef_list.append(
                    findcoef(
                        yc,
                        soldict[sol][9],
                        soldict[sol][10]))

    if len(time_list) == 1:
        function = function_list[0]
        order = order_list[0]
        domain = domain_list[0]
        coef = coef_list[0]
    elif len(time_list) < 1:
        return None, None, None, None
    else:
        # determine the points closest in time to the observation
        t_arr = np.array(time_list)
        id_min = t_arr.argmin()
        function = function_list[id_min]
        order = order_list[id_min]
        domain = order_list[domain]
        coef = coef_list[id_min]

        # If xarr is None, return the solution closest in time to the
        # obsevation
        if coef is None:
            return function, order, coef

        # if nearest, return that
        if nearest:
            return function, order, coef

        # If xarr, then calculation w_arr for each of the solutions available,
        # After calculating the solution, calculated the time weighted average
        # wavelength calibration for that pixel array.  Then recalculate the solution
        # using the same funcitonal form as the best function
        w_ave = xarr * 0.0
        wei = 0.0
        for i, t in enumerate(time_list):
            if t == 0:
                return function, order, coef
            ws = WavelengthSolution.WavelengthSolution(
                xarr,
                xarr,
                function=function_list[i],
                order=order_list[i])
            ws.set_coef(coef_list[i])
            try:
                w_ave += ws.value(xarr) / t ** 2
                wei += 1.0 / t ** 2
            except:
                pass
        w_ave = w_ave / wei
        # for the purposes of speed, we can sparsely sample the arrays

        j = int(len(xarr) / order / 8)
        ws = WavelengthSolution.WavelengthSolution(
            xarr[
                ::j], w_ave[
                ::j], function=function, order=order)
        ws.fit()
        coef = ws.coef

    return function, order, coef, domain
Beispiel #7
0
def wavemap(hdu,
            soldict,
            caltype='line',
            function='poly',
            order=3,
            blank=0,
            nearest=False,
            array_only=False,
            clobber=True,
            log=None,
            verbose=True):
    """Read in an image and a set of wavlength solutions.  Calculate the best
       wavelength solution for a given dataset and then apply that data set to the
       image

     return
    """

    # set up the time of the observation
    dateobs = saltkey.get('DATE-OBS', hdu[0])
    utctime = saltkey.get('TIME-OBS', hdu[0])
    exptime = saltkey.get('EXPTIME', hdu[0])
    instrume = saltkey.get('INSTRUME', hdu[0]).strip()
    grating = saltkey.get('GRATING', hdu[0]).strip()
    if caltype == 'line':
        grang = saltkey.get('GRTILT', hdu[0])
        arang = saltkey.get('CAMANG', hdu[0])
    else:
        grang = saltkey.get('GR-ANGLE', hdu[0])
        arang = saltkey.get('AR-ANGLE', hdu[0])
    filtername = saltkey.get('FILTER', hdu[0]).strip()
    slitname = saltkey.get('MASKID', hdu[0])
    slit = st.getslitsize(slitname)
    xbin, ybin = saltkey.ccdbin(hdu[0])

    timeobs = sr.enterdatetime('%s %s' % (dateobs, utctime))

    # check to see if there is more than one solution
    if caltype == 'line':
        if len(soldict) == 1:
            sol = soldict.keys()[0]
            slitid = None
            if not sr.matchobservations(soldict[sol], instrume, grating, grang,
                                        arang, filtername, slitid):
                msg = 'Observations do not match setup for transformation but using the solution anyway'
                if log:
                    log.warning(msg)

    for i in range(1, len(hdu)):
        if hdu[i].name == 'SCI':
            if log:
                log.message('Correcting extension %i' % i)
            istart = int(0.5 * len(hdu[i].data))

            # open up the data
            # set up the xarr and initial wavlength solution
            xarr = np.arange(len(hdu[i].data[istart]), dtype='int64')

            # get the slitid
            try:
                slitid = saltkey.get('SLITNAME', hdu[i])
            except:
                slitid = None

            #check to see if wavext is already there and if so, then check update
            #that for the transformation from xshift to wavelength
            if saltkey.found('WAVEXT', hdu[i]):
                w_ext = saltkey.get('WAVEXT', hdu[i]) - 1
                wavemap = hdu[w_ext].data
                function, order, coef = sr.findlinesol(
                    soldict, istart, nearest, timeobs, exptime, instrume,
                    grating, grang, arang, filtername, slitid, xarr)
                ws = WavelengthSolution.WavelengthSolution(xarr,
                                                           xarr,
                                                           function=function,
                                                           order=order)
                ws.set_coef(coef)
                for j in range(len(hdu[i].data)):
                    wavemap[j, :] = ws.value(wavemap[j, :])
                if array_only: return wavemap
                hdu[w_ext].data = wavemap
                continue

            # set up a wavelength solution -- still in here for testing MOS data
            try:
                w_arr = sr.findsol(xarr, soldict, istart, caltype, nearest,
                                   timeobs, exptime, instrume, grating, grang,
                                   arang, filtername, slit, xbin, ybin, slitid,
                                   function, order)
            except SALTSpecError as e:
                if slitid:
                    msg = 'SLITID %s: %s' % (slitid, e)
                    if log:
                        log.warning(msg)
                    continue
                else:
                    raise SALTSpecError(e)

            if w_arr is None:
                w_arr = sr.findsol(xarr, soldict, istart, 'rss', nearest,
                                   timeobs, exptime, instrume, grating, grang,
                                   arang, filtername, slit, xbin, ybin, slitid,
                                   function, order)

            # for each line in the data, determine the wavelength solution
            # for a given line in the image
            wavemap = np.zeros_like(hdu[i].data)
            for j in range(len(hdu[i].data)):
                # find the wavelength solution for the data
                w_arr = sr.findsol(xarr, soldict, j, caltype, nearest, timeobs,
                                   exptime, instrume, grating, grang, arang,
                                   filtername, slit, xbin, ybin, slitid,
                                   function, order)
                if w_arr is not None: wavemap[j, :] = w_arr
            if array_only: return wavemap

            # write out the oimg
            hduwav = fits.ImageHDU(data=wavemap,
                                   header=hdu[i].header,
                                   name='WAV')
            hdu.append(hduwav)
            saltkey.new('WAVEXT',
                        len(hdu) - 1, 'Extension for Wavelength Map', hdu[i])

    return hdu
Beispiel #8
0
def specidentify(images,
                 linelist,
                 outfile,
                 guesstype='rss',
                 guessfile='',
                 automethod='Matchlines',
                 function='poly',
                 order=3,
                 rstep=100,
                 rstart='middlerow',
                 mdiff=5,
                 thresh=3,
                 niter=5,
                 smooth=0,
                 subback=0,
                 inter=True,
                 startext=0,
                 clobber=False,
                 textcolor='black',
                 preprocess=False,
                 logfile='salt.log',
                 verbose=True):

    with logging(logfile, debug) as log:

        # set up the variables
        infiles = []
        outfiles = []

        # Check the input images
        infiles = saltio.argunpack('Input', images)

        # create list of output files
        outfiles = saltio.argunpack('Output', outfile)

        # open the line lists
        slines, sfluxes = st.readlinelist(linelist)

        # Identify the lines in each file
        for img, ofile in zip(infiles, outfiles):

            # open the image
            hdu = saltio.openfits(img)

            # get the basic information about the spectrograph
            dateobs = saltkey.get('DATE-OBS', hdu[0])
            try:
                utctime = saltkey.get('UTC-OBS', hdu[0])
            except SaltError:
                utctime = saltkey.get('TIME-OBS', hdu[0])

            instrume = saltkey.get('INSTRUME', hdu[0]).strip()
            grating = saltkey.get('GRATING', hdu[0]).strip()
            grang = saltkey.get('GR-ANGLE', hdu[0])
            grasteps = saltkey.get('GRTILT', hdu[0])
            arang = saltkey.get('AR-ANGLE', hdu[0])
            arsteps = saltkey.get('CAMANG', hdu[0])
            rssfilter = saltkey.get('FILTER', hdu[0])
            specmode = saltkey.get('OBSMODE', hdu[0])
            masktype = saltkey.get('MASKTYP', hdu[0]).strip().upper()
            slitname = saltkey.get('MASKID', hdu[0])
            xbin, ybin = saltkey.ccdbin(hdu[0], img)

            for i in range(startext, len(hdu)):
                if hdu[i].name == 'SCI':
                    log.message('Proccessing extension %i in  %s' % (i, img))
                    # things that will change for each slit

                    if masktype == 'LONGSLIT':
                        slit = st.getslitsize(slitname)
                        xpos = -0.2666
                        ypos = 0.0117
                        objid = None
                    elif masktype == 'MOS':
                        slit = 1.
                        #slit=saltkey.get('SLIT', hdu[i])

                        # set up the x and y positions
                        miny = hdu[i].header['MINY']
                        maxy = hdu[i].header['MAXY']
                        ras = hdu[i].header['SLIT_RA']
                        des = hdu[i].header['SLIT_DEC']
                        objid = hdu[i].header['SLITNAME']

                        # TODO: Check the perfomance of masks at different PA
                        rac = hdu[0].header['MASK_RA']
                        dec = hdu[0].header['MASK_DEC']
                        pac = hdu[0].header['PA']

                        # these are hard wired at the moment
                        xpixscale = 0.1267 * xbin
                        ypixscale = 0.1267 * ybin
                        cx = int(3162 / xbin)
                        cy = int(2050 / ybin)

                        x, y = mt.convert_fromsky(ras,
                                                  des,
                                                  rac,
                                                  dec,
                                                  xpixscale=xpixscale,
                                                  ypixscale=ypixscale,
                                                  position_angle=-pac,
                                                  ccd_cx=cx,
                                                  ccd_cy=cy)
                        xpos = 0.015 * 2 * (cx - x[0])
                        ypos = 0.0117
                    else:
                        msg = '%s is not a currently supported masktype' % masktype
                        raise SALTSpecError(msg)

                    if instrume not in ['PFIS', 'RSS']:
                        msg = '%s is not a currently supported instrument' % instrume
                        raise SALTSpecError(msg)

                    # create RSS Model
                    rss = RSSModel.RSSModel(grating_name=grating.strip(),
                                            gratang=grang,
                                            camang=arang,
                                            slit=slit,
                                            xbin=xbin,
                                            ybin=ybin,
                                            xpos=xpos,
                                            ypos=ypos)
                    res = 1e7 * rss.calc_resolelement(rss.alpha(), -rss.beta())
                    dres = res / 10.0
                    wcen = 1e7 * rss.calc_centralwavelength()
                    R = rss.calc_resolution(wcen / 1e7, rss.alpha(),
                                            -rss.beta())
                    logmsg = '\nGrating\tGR-ANGLE\tAR-ANGLE\tSlit\tWCEN\tR\n'
                    logmsg += '%s\t%8.3f\t%8.3f\t%4.2f\t%6.2f\t%4f\n' % (
                        grating, grang, arang, slit, wcen, R)
                    if log:
                        log.message(logmsg, with_header=False)

                    # set up the data for the source
                    try:
                        data = hdu[i].data
                    except Exception, e:
                        message = 'Unable to read in data array in %s because %s' % (
                            img, e)
                        raise SALTSpecError(message)

                    # set up the center row
                    if rstart == 'middlerow':
                        ystart = int(0.5 * len(data))
                    else:
                        ystart = int(rstart)

                    rss.gamma = 0.0
                    if masktype == 'MOS':
                        rss.gamma = 180.0 / math.pi * math.atan(
                            (y * rss.detector.pix_size * rss.detector.ybin -
                             0.5 * rss.detector.find_height()) /
                            rss.camera.focallength)

                    # set up the xarr array based on the image
                    xarr = np.arange(len(data[ystart]), dtype='int64')

                    # get the guess for the wavelength solution
                    if guesstype == 'rss':
                        # set up the rss model
                        ws = st.useRSSModel(xarr,
                                            rss,
                                            function=function,
                                            order=order,
                                            gamma=rss.gamma)
                        if function in ['legendre', 'chebyshev']:
                            ws.func.func.domain = [xarr.min(), xarr.max()]
                    elif guesstype == 'file':
                        soldict = {}
                        soldict = readsolascii(guessfile, soldict)
                        timeobs = enterdatetime('%s %s' % (dateobs, utctime))
                        exptime = saltkey.get('EXPTIME', hdu[0])
                        filtername = saltkey.get('FILTER', hdu[0]).strip()
                        try:
                            slitid = saltkey.get('SLITNAME', hdu[i])
                        except:
                            slitid = None

                        function, order, coef, domain = findlinesol(soldict,
                                                                    ystart,
                                                                    True,
                                                                    timeobs,
                                                                    exptime,
                                                                    instrume,
                                                                    grating,
                                                                    grang,
                                                                    arang,
                                                                    filtername,
                                                                    slitid,
                                                                    xarr=xarr)
                        ws = WavelengthSolution.WavelengthSolution(
                            xarr, xarr, function=function, order=order)
                        ws.func.func.domain = domain
                        ws.set_coef(coef)
                    else:
                        raise SALTSpecError(
                            'This guesstype is not currently supported')

                    # identify the spectral lines
                    ImageSolution = identify(data,
                                             slines,
                                             sfluxes,
                                             xarr,
                                             ystart,
                                             ws=ws,
                                             function=function,
                                             order=order,
                                             rstep=rstep,
                                             mdiff=mdiff,
                                             thresh=thresh,
                                             niter=niter,
                                             method=automethod,
                                             res=res,
                                             dres=dres,
                                             smooth=smooth,
                                             inter=inter,
                                             filename=img,
                                             subback=0,
                                             textcolor=textcolor,
                                             preprocess=preprocess,
                                             log=log,
                                             verbose=verbose)

                    if outfile and len(ImageSolution):
                        writeIS(ImageSolution,
                                outfile,
                                dateobs=dateobs,
                                utctime=utctime,
                                instrume=instrume,
                                grating=grating,
                                grang=grang,
                                grasteps=grasteps,
                                arsteps=arsteps,
                                arang=arang,
                                rfilter=rssfilter,
                                slit=slit,
                                xbin=xbin,
                                ybin=ybin,
                                objid=objid,
                                filename=img,
                                log=log,
                                verbose=verbose)
Beispiel #9
0
def findxcor(xarr, farr, swarr, sfarr, ws, dcoef=None, ndstep=20, best=False,
             inttype='interp', debug=False):
    """Find the solution using crosscorrelation of the wavelength solution.
       An initial guess needs to be supplied along with the variation in
       each coefficient and the number of steps to calculate the correlation.
       The input wavelength and flux for the known spectral features should
       be in the format where they have already
       been convolved with the response function of the spectrograph

       xarr--Pixel coordinates of the image

       farr--Flux values for each pixel

       swarr--Input wavelengths of known spectral features

       sfarr--fluxes of known spectral features

       ws--current wavelength solution

       dcoef--Variation over each coefficient for correlation

       ndstep--number of steps to sample over

       best--if True, return the best value
             if False, return an interpolated value

       inttype--type of interpolation

    """

    # cross-correlate the spectral lines and the observed fluxes in order to
    # refine the solution
    try:
        nws = copy.deepcopy(ws)
    except:
        nws = WavelengthSolution.WavelengthSolution(
            ws.x_arr, ws.w_arr, ws.function, ws.order, 
            domain = ws.func.func.domain)
        nws.coef.set_coef(ws.coef)
 
    # create the range of coefficents
    if dcoef is None:
        dcoef = ws.coef * 0.0 + 1.0

    dlist = mod_coef(ws.coef, dcoef, 0, ndstep)
    # loop through them and deteremine the best cofficient
    cc_arr = np.zeros(len(dlist), dtype=float)
    
    for i in range(len(dlist)):
        # set the coeficient
        nws.set_coef(dlist[i])

        # set the wavelegnth coverage
        warr = nws.value(xarr)

        # resample the artificial spectrum at the same wavelengths as the
        # observed spectrum
        asfarr = interpolate(
            warr, swarr, sfarr, type=inttype, left=0.0, right=0.0)

        # calculate the correlation value
        cc_arr[i] = ncor(farr, asfarr)
        if debug:
            print(cc_arr[i], " ".join(["%f" % k for k in dlist[i]]))

    # now set the best coefficients
    i = cc_arr.argmax()
    bcoef = dlist[i]
    nws.set_coef(bcoef)
    if best:
        return nws

    # interpoloate over the values to determine the best value
    darr = np.array(dlist)
    for j in range(len(nws.coef)):
        if dcoef[j] != 0.0:
            i = cc_arr.argsort()[::-1]
            tk = np.polyfit(darr[:, j][i[0:5]], cc_arr[i[0:5]], 2)

            if tk[0] == 0:
                bval = 0
            else:
                bval = -0.5 * tk[1] / tk[0]

            # make sure that the best value is close
            if abs(bval - bcoef[j]) < 2 * dcoef[j] / ndstep:
                bcoef[j] = bval

            # coef=np.polyfit(dlist[:][j], cc_arr, 2)
            # nws.coef[j]=-0.5*coef[1]/coef[0]

    nws.set_coef(bcoef)

    return nws