Example #1
0
def find_peaks_2(s):
    """ 
    """
    logger.info('using calibration line location algorithm 2')
    s = s[:-20]
    s -= np.amin(s)
    coeffs = np.polyfit(np.arange(len(s)), s, 9)
    s_fit = np.polyval(coeffs, np.arange(len(s)))
    sp = s - s_fit
    sp -= np.amin(sp)
    peaks_i = argrelextrema(sp, np.greater)
    peaks_y = sp[peaks_i]
#     big_peaks = peaks_i[0][np.where(peaks_y > 1.7 * peaks_y.mean())]
    big_peaks = peaks_i[0][np.where(peaks_y > 1.4 * peaks_y.mean())]

#     import pylab as pl
#     pl.figure(figsize=(20, 5))
#     pl.cla()
#     pl.plot(s + 20, 'r-')
#     pl.plot(sp, 'k-')
#     pl.plot(s_fit + 20, 'r-')
#     pl.plot(big_peaks, sp[big_peaks], 'ro')
#     pl.show()
    
    return(big_peaks)
def find_peaks_1(s):
    """
    """
    logger.info('using calibration line location algorithm 1')
    peaks_i = argrelextrema(s, np.greater)[0]
    peaks_y = s[peaks_i]
    return(peaks_i[np.where(peaks_y > 3.0 * peaks_y.mean())])
def find_peaks_2(s):
    """ 
    """
    logger.info('using calibration line location algorithm 2')
    s = s[:-20]
    s -= np.amin(s)
    coeffs = np.polyfit(np.arange(len(s)), s, 9)
    s_fit = np.polyval(coeffs, np.arange(len(s)))
    sp = s - s_fit
    sp -= np.amin(sp)
    peaks_i = argrelextrema(sp, np.greater)
    peaks_y = sp[peaks_i]
#     big_peaks = peaks_i[0][np.where(peaks_y > 1.7 * peaks_y.mean())]
    big_peaks = peaks_i[0][np.where(peaks_y > 1.4 * peaks_y.mean())]

#     import pylab as pl
#     pl.figure(figsize=(20, 5))
#     pl.cla()
#     pl.plot(s + 20, 'r-')
#     pl.plot(sp, 'k-')
#     pl.plot(s_fit + 20, 'r-')
#     pl.plot(big_peaks, sp[big_peaks], 'ro')
#     pl.show()
    
    return(big_peaks)
Example #4
0
def find_peaks_1(s):
    """
    """
    logger.info('using calibration line location algorithm 1')
    peaks_i = argrelextrema(s, np.greater)[0]
    peaks_y = s[peaks_i]
    return(peaks_i[np.where(peaks_y > 3.0 * peaks_y.mean())])
Example #5
0
def getMinima(errs, nr=-1):
    
    inds = argrelextrema(errs, np.less,order=1, mode='wrap')
    indTable = np.zeros((len(inds[0]),len(errs.shape)))
    for i in range(0,len(inds)):
        indTable[:,i] = inds[i]
    if nr == -1:
        return indTable
    else:
        return indTable[nr,:]
Example #6
0
def getMinima(errs, nr=-1):
    
    inds = argrelextrema(errs, np.less,order=1, mode='wrap')
    indTable = np.zeros((len(inds[0]),len(errs.shape)))
    for i in range(0,len(inds)):
        indTable[:,i] = inds[i]
    if nr == -1:
        return indTable
    else:
        return indTable[nr,:]
def find_peaks_2(s, eta=None, arc=None):
    """ 
    """
    logger.info('using calibration line location algorithm 2')
    s         = s[:-20] # Crop out the back portion
    s        -= np.amin(s)
    coeffs    = np.polyfit(np.arange(len(s)), s, 10)
    s_fit     = np.polyval(coeffs, np.arange(len(s)))
    sp        = s - s_fit
    if eta is not None or arc is not None:
        sp[0:20] = 0. # Set the first few pixels to zero since we don't want false lines
    sp       -= np.amin(sp)
    sp       -= np.median(sp)
    #print(np.median(sp), 1.1*np.median(sp))
    if eta is not None or arc is not None:
        #peaks_i   = argrelextrema(sp, np.greater, order=2)
        #print(peaks_i)
        peaks_i   = find_peaks_cwt(sp, [4,5,6,7,8])#, min_length=20)#, min_snr=3)
        #print('PEAKS', peaks_i)
    else:
        peaks_i   = argrelextrema(sp, np.greater)
    peaks_y   = sp[peaks_i]
    #for p,z in zip(peaks_i[0], peaks_y):
    #    print(p, z, z/peaks_y.mean())
#     big_peaks = peaks_i[0][np.where(peaks_y > 1.7 * peaks_y.mean())]
    if eta is not None:
        #big_peaks = peaks_i[np.where(peaks_y > 1.1 * sp.mean())]
        #big_peaks = peaks_i[np.where(peaks_y > 1.1 * np.median(sp))]
        big_peaks = peaks_i[np.where(peaks_y >= 0.15)] # XXX We could change this to use percentiles to estimate the cutoff
        #print(big_peaks)
    elif arc is not None:
        s         = s - np.median(s)
        peaks_y   = s[peaks_i]
        big_peaks = peaks_i[np.where(peaks_y >= 0.005)] # XXX We could change this to use percentiles to estimate the cutoff
    else:
        big_peaks = peaks_i[0][np.where(peaks_y > 1.4 * peaks_y.mean())]
    
    ### TESTING
    '''
    import pylab as pl
    pl.figure(figsize=(15, 5))
    pl.cla()
    if eta is not None or arc is not None: offsetPlot = 0
    else: offsetPlot = 20
    pl.plot(s + offsetPlot, 'r-')
    pl.plot(sp, 'k-')
    pl.plot(s_fit + offsetPlot, 'm-', alpha=0.5)
    for peak in peaks_i:
        if peak == peaks_i[0]: pl.axvline(peak, color='r', ls=':', lw=1.5, label='peaks')
        else: pl.axvline(peak, color='r', ls=':', lw=1.5)
    #pl.scatter(big_peaks, sp[big_peaks], color='C0')
    for peak in big_peaks:
        if peak == big_peaks[0]: pl.axvline(peak, color='b', ls='--', lw=0.9, label='big peaks')
        else: pl.axvline(peak, color='b', ls='--', lw=0.9)
    pl.legend()
    pl.show()
    #sys.exit()
    '''
    ### TESTING
    
    
    return(big_peaks)
img = cv2.imread(img_name, 0)
org_img = cv2.imread(img_name, 0)

# flatten image, remove black (background )
flat_img = img.ravel()
clean_data = np.delete(flat_img, np.where(flat_img == 0))

# PROBABILITY DENSITY PLOT
# plot data in histogram with a gaussian kernel density estimate
p = sns.distplot(clean_data, hist=True, kde=True, bins=list(range(1, 255)))

# FIND MINIMA
frequencies = [h.get_height() for h in p.patches]
np_freq = np.asarray(frequencies)
# TODO: calculate order so that it will work for any image
minm = argrelextrema(np_freq, np.less, order=20)
minima = minm[0].tolist()

# IMAGE MANIPULATION
csf = minima[1]
gm = minima[2] - 50
wm = 255
# height
for up in range(img.shape[0]):
    for across in range(img.shape[1]):
        selected = img[up][across]
        if selected < minima[1] and selected != 0:
            img[up][across] = csf
        elif selected > minima[2]:
            img[up][across] = wm
        elif selected > minima[1] and selected < minima[2]:
def find_spectral_trace(data, numrows=5, eta=None, arc=None, plot=False):
    """
    Locates sky/etalon lines in the bottom 5 rows (is this really optimal?) of the order image data. 
    I fixed the above lines to check the bottom 5 rows and top 5 rows for which has more sky. - CAT
    Finds strongest peaks, sorts them, traces them, returns the average of the traces.
    Rejects line pairs that are too close together.
    Returns spectral trace as 1-d array.  Throws exception if can't find or trace lines.
    """
    SKY_SIGMA           = 2. #2.25 # old value
    MIN_LINE_SEPARATION = 5
    
    # transpose the array because spectroid can only read horizontal peaks for now
    data_t0  = data.transpose()

#     data_t = data_t[:, padding + 5:data_t.shape[1] - 5 - padding]
    data_t   = data_t0[:, 5:data_t0.shape[1] - 5]    

    crit_val = np.median(data_t) # Get a value for the background
    #print('Crit', crit_val, 2*crit_val)

    # This is a check to see if we should use the front rows or a few rows in
    if len(np.where(data_t[:, 0:numrows].flatten() > 2*crit_val)[0]) > 1000: 
        s = np.sum(data_t[:, numrows:numrows*2], axis=1) # This is a few rows in
    else:
        s = np.sum(data_t[:, 0:numrows], axis=1) # This is the first few rows

    if plot:
        import pylab as pl
        sky_thres = SKY_SIGMA * np.median(s)
        #print('SIG', np.median(s), SKY_SIGMA, sky_thres)
        pl.figure(facecolor='white')
        pl.cla()
        pl.plot(s, 'k-')
        pl.axhline(SKY_SIGMA * np.median(s), c='r', ls=':', label='sigma * median')
        pl.axhline(2.25 * np.median(s), c='b', ls=':', label='2.25 * median')
        pl.xlim(0, data_t.shape[0])
        pl.xlabel('column (pixels)')
        pl.ylabel('intensity summed over 5 rows (DN)')
        ymin, ymax = pl.ylim()
        pl.ylim(0, ymax)
        pl.legend()
        pl.show()

    # finds column indices of maxima
    if eta is not None:
        maxima_c = argrelextrema(s, np.greater, order=3) 
    elif arc is not None:
        maxima_c = argrelextrema(s, np.greater, order=3) 
    else:
        maxima_c = argrelextrema(s, np.greater)    
    
    # find indices in maxima_c of maxima with intensity 
    # greater than SKY_SIGMA * median extrema height
    sky_thres = SKY_SIGMA * np.median(s)
    locmaxes  = np.where(s[maxima_c[0]] > sky_thres)

    # indices in s or peaks
    maxes = np.array(maxima_c[0][locmaxes[0]])

    logger.debug('n sky/etalon/arc line peaks with intensity > {:.0f} = {}'.format(
                sky_thres, len(maxes)))

    deletelist = []
           
    # remove adjacent sky lines that are closer than MIN_LINE_SEPARATION pixels
    for i in range(1, len(maxes)):
        if abs(maxes[i] - maxes[i - 1]) < MIN_LINE_SEPARATION:
            deletelist.append(i)
    maxes = np.delete(maxes, deletelist, None)

    peaks = s[maxes] 

    sortorder = np.argsort(peaks)
            
    maxes = maxes[sortorder]
    maxes = maxes[::-1]

    # Try to find some fainter lines if the threshold was too large
    #print('MAXES', maxes, len(maxes), SKY_SIGMA)
    if len(maxes) < 5:
        for SKY_SIGMA in [1.5, 1.2]: 
            sky_thres = SKY_SIGMA * np.median(s)
            locmaxes  = np.where(s[maxima_c[0]] > sky_thres)

            # indices in s or peaks
            maxes = np.array(maxima_c[0][locmaxes[0]])
            
            logger.debug('n sky/etalon/arc line peaks with intensity > {:.0f} = {}'.format(
                    sky_thres, len(maxes)))

            deletelist = []
           
            # remove adjacent sky lines that are closer than MIN_LINE_SEPARATION pixels
            for i in range(1, len(maxes)):
                if abs(maxes[i] - maxes[i - 1]) < MIN_LINE_SEPARATION:
                    deletelist.append(i)
            maxes = np.delete(maxes, deletelist, None)

            peaks = s[maxes] 

            sortorder = np.argsort(peaks)
                    
            maxes = maxes[sortorder]
            maxes = maxes[::-1]

            if len(maxes) >= 5: # We have enough sky/etalon/arc lines
                break

    logger.info('n unblended sky/etalon/arc line peaks with intensity > {:.0f} = {}'.format(
                    sky_thres, len(maxes)))
    
    if plot:
        print('MAXES', maxes)
        pl.figure(facecolor='white')
        pl.cla()
        pl.plot(s, 'k-')
        pl.axhline(sky_thres, c='r', ls=':')
        pl.xlim(0, data_t.shape[0])
        pl.xlabel('column (pixels)')
        pl.ylabel('intensity summed over 5 rows (DN)')
        ymin, ymax = pl.ylim()
        pl.ylim(0, ymax)
        #pl.show()
        for max1 in maxes: pl.axvline(max1, color='b', ls='--', alpha=0.5, lw=0.5)

        pl.figure(27847)
        pl.imshow(data_t, origin='lower', aspect='auto')
        for max1 in maxes: pl.axhline(max1, color='r', ls='--', alpha=0.5, lw=0.5)
        pl.show()
    
    centroid_sky_sum = np.zeros(data_t.shape[1])
    fitnumber        = 0

    centroids = []

    lowlim, uplim = 10, 1024-14
    if nirspec_constants.upgrade:
        lowlim, uplim = 20, 2048-48

    for maxskyloc in maxes:
        if lowlim < maxskyloc < uplim:
            
            centroid_sky = trace_sky_line(data_t, maxskyloc, eta=eta, arc=arc)
           
            if centroid_sky is None:
                continue

            centroids.append(centroid_sky)

            fitnumber += 1

            #if eta is None:
            #    if fitnumber > 2: # Why are we limiting this?
            #        break



    if fitnumber > 0:
        logger.info(str(fitnumber) + ' sky/etalon/arc lines selected for spectral rectification')
        return centroids
        #return centroid_sky_sum / fitnumber
    
    logger.warning('failed to find sky/etalon/arc line trace')
    raise StandardError('failed to find sky/etalon/arc line trace')
Example #10
0
def find_spectral_trace(data):
    """
    Locates sky lines in the bottom 5 rows (is this really optimal?) of the order image data.
    Finds strongest peaks, sorts them, traces them, returns the average of the traces.
    Rejects line pairs that are too close together.
    Returns spectral trace as 1-d array.  Throws exception if can't find or trace lines.
    """

    # transpose the array because spectroid can only read horizontal peaks for
    # now
    data_t = data.transpose()

    #     data_t = data_t[:, padding + 5:data_t.shape[1] - 5 - padding]
    data_t = data_t[:, 5:data_t.shape[1] - 5]
    s = np.sum(data_t[:, 0:5], axis=1)

    #     import pylab as pl
    #     pl.figure(facecolor='white')
    #     pl.cla()
    #     pl.plot(s, 'k-')
    #     pl.xlim(0, 1024)
    #     pl.xlabel('column (pixels)')
    #     pl.ylabel('intensity summed over 5 rows (DN)')
    #     pl.show()

    # finds column indices of maxima
    maxima_c = argrelextrema(s, np.greater)

    # find indices in maxima_c of maxima with intensity
    # greater than SKY_SIGMA * mean extrema height
    locmaxes = np.where(s[maxima_c[0]] > SKY_SIGMA * s.mean())

    # indices in s or peaks
    maxes = np.array(maxima_c[0][locmaxes[0]])

    logger.info('n sky line peaks with intensity > {:.0f} = {}'.format(
        SKY_SIGMA * s.mean(), len(maxes)))

    deletelist = []

    # remove adjacent sky lines that are closer than MIN_LINE_SEPARATION pixels
    for i in range(1, len(maxes)):
        if abs(maxes[i] - maxes[i - 1]) < MIN_LINE_SEPARATION:
            deletelist.append(i)
    maxes = np.delete(maxes, deletelist, None)

    peaks = s[maxes]

    sortorder = np.argsort(peaks)

    maxes = maxes[sortorder]
    maxes = maxes[::-1]

    centroid_sky_sum = np.zeros(data_t.shape[1])
    fitnumber = 0

    for maxskyloc in maxes:
        if 10 < maxskyloc < 1010:

            centroid_sky = trace_sky_line(data_t, maxskyloc)

            if centroid_sky is None:
                continue

            fitnumber += 1
            centroid_sky_sum = centroid_sky_sum + \
                centroid_sky - centroid_sky[0]

            if fitnumber > 2:
                break

    if centroid_sky_sum.any():
        logger.info(
            str(fitnumber) + ' sky lines used for spectral rectification')
        return centroid_sky_sum / fitnumber

    logger.warning('failed to find sky line trace')
    raise Exception('failed to find sky line trace')
Example #11
0
def find_spectral_trace(data):
    """
    Locates sky lines in the bottom 5 rows (is this really optimal?) of the order image data. 
    Finds strongest peaks, sorts them, traces them, returns the average of the traces.
    Rejects line pairs that are too close together.
    Returns spectral trace as 1-d array.  Throws exception if can't find or trace lines.
    """
    
    # transpose the array because spectroid can only read horizontal peaks for now
    data_t = data.transpose()

#     data_t = data_t[:, padding + 5:data_t.shape[1] - 5 - padding]
    data_t = data_t[:, 5:data_t.shape[1] - 5]
    s = np.sum(data_t[:, 0:5], axis=1)
    
#     import pylab as pl
#     pl.figure(facecolor='white')
#     pl.cla()
#     pl.plot(s, 'k-')
#     pl.xlim(0, 1024)
#     pl.xlabel('column (pixels)')
#     pl.ylabel('intensity summed over 5 rows (DN)')
#     pl.show()

    # finds column indices of maxima
    maxima_c = argrelextrema(s, np.greater)     
    
    # find indices in maxima_c of maxima with intensity 
    # greater than SKY_SIGMA * mean extrema height
    locmaxes = np.where(s[maxima_c[0]] > SKY_SIGMA * s.mean())
    
    # indices in s or peaks
    maxes = np.array(maxima_c[0][locmaxes[0]])
    
    logger.info('n sky lines peaks with intensity > {:.0f} = {}'.format(
            SKY_SIGMA * s.mean(), len(maxes)))

    deletelist = []
   
    # remove adjacent sky lines that are closer than MIN_LINE_SEPARATION pixels
    for i in range(1, len(maxes)):
        if abs(maxes[i] - maxes[i - 1]) < MIN_LINE_SEPARATION:
            deletelist.append(i)
    maxes = np.delete(maxes, deletelist, None)

    peaks = s[maxes]        

    sortorder = np.argsort(peaks)
            
    maxes = maxes[sortorder]
    maxes = maxes[::-1]

    centroid_sky_sum = np.zeros(data_t.shape[1])
    fitnumber = 0

    for maxskyloc in maxes:
        if 10 < maxskyloc < 1010:
            
            centroid_sky = trace_sky_line(data_t, maxskyloc)
           
            if centroid_sky is None:
                continue

            fitnumber += 1
            centroid_sky_sum = centroid_sky_sum + centroid_sky - centroid_sky[0]

            if fitnumber > 2:
                break

    if centroid_sky_sum.any():
        logger.info(str(fitnumber) + ' sky lines used for spectral rectification')
        return centroid_sky_sum / fitnumber
    
    logger.warning('failed to find sky line trace')
    raise StandardError('failed to find sky line trace')
Example #12
0
def find_spectral_trace(data, padding):
    
    # transpose the array because spectroid can only read horizontal peaks for now
    npsts = data.transpose()

    # The order cutout has padding on each side. In order to find the sky lines we should 
    # only look at the central section of the cut out array
#     npsts = npsts[:, padding + 5:npsts.shape[1] - 5 - padding]
    npsts = npsts[:, 5:npsts.shape[1] - 5]
    cc = np.sum(npsts[:, 0:5], axis=1)
    
#     import pylab as pl
#     pl.figure(facecolor='white')
#     pl.cla()
#     pl.plot(cc, 'k-')
#     pl.xlim(0, 1024)
#     pl.xlabel('column (pixels)')
#     pl.ylabel('intensity summed over 5 rows (DN)')
#     pl.show()

    locpeaks = argrelextrema(cc, np.greater)     
    locmaxes = np.where(cc[locpeaks[0]] > SKY_SIGMA * cc.mean())
    maxes = np.array(locpeaks[0][locmaxes[0]])

    deletelist = []
   
    # remove adjacent sky lines that are closer than MIN_LINE_SEPARATION pixels
    for i in range(1, len(maxes)):
        if abs(maxes[i] - maxes[i - 1]) < MIN_LINE_SEPARATION:
            deletelist.append(i)
    maxes = np.delete(maxes, deletelist, None)

    peaks = cc[maxes]        

    sortorder = np.argsort(peaks)
            
    maxes = maxes[sortorder]
    maxes = maxes[::-1]

    skydict = {}
    centroid_sky_sum = np.array([])
    fitnumber = 0

    for maxskyloc in maxes:
        if 10 < maxskyloc < 1010:
            
            centroid_sky = trace_sky_line(npsts, maxskyloc)
           
            if centroid_sky is None:
                continue  # skip this skyline

            # average up the good ones
            # if badfit < 10:
            if True:
                skydict[fitnumber] = centroid_sky
                fitnumber += 1
                if centroid_sky_sum.any():
                    centroid_sky_sum = centroid_sky_sum + centroid_sky - centroid_sky[0]
                else:
                    centroid_sky_sum = centroid_sky - centroid_sky[0]
            if fitnumber > 2:
                break

    if centroid_sky_sum.any():
        logger.info(str(fitnumber) + ' sky lines used for spectral rectification')
        return centroid_sky_sum / fitnumber
    
    logger.warning('failed to find sky line trace')
    raise StandardError('failed to find sky line trace')