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 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')
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')
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')
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')