def update(self): i = self.i self.artists['mlines'] = [] a = self.ax s = self.spec[i] wa, fl, er, co = s.wa, s.fl, s.er, s.co if self.models[i] is not None and (co > 0).any(): temp = co * self.models[i] a.plot(wa, temp, color='orange') a.set_title(self.filenames[i]) if self.zp1 is not None: self.update_lines() if self.ticks is not None: if not np.isnan(co).all() and not self.opt.co_is_sky: f = np.interp(self.ticks.wa, wa, co) else: f = np.interp(self.ticks.wa, wa, fl) height = 0.08 * np.percentile(fl, 90) for j, t in enumerate(self.ticks): if self.opt.showticks: T, Tlabels = plot_tick_wa(a, t.wa, f[j], height, t, tickz=self.opt.tickz) self.artists['ticks'].extend(T) self.artists['ticklabels'].extend(Tlabels) if self.opt.f26 is not None and self.opt.f26.regions is not None: plotregions(a, self.opt.f26.regions.wmin, self.opt.f26.regions.wmax) if self.opt.features is not None: f = self.opt.features sortfl = np.sort(fl[er > 0]) ref = sortfl[int(len(sortfl)*0.95)] - sortfl[int(len(sortfl)*0.05)] wedge = np.concatenate([f.wa0, f.wa1]) axvlines(wedge, ax=a, colors='k', alpha=0.7) temp = co[np.array([indexnear(wa, wav) for wav in f.wac])] ymin = temp + ref * 0.1 ymax = ymin + ref * 0.2 a.vlines(f.wac, ymin, ymax, colors='g') for j, f in enumerate(f): a.text(f['wac'], ymax[j] + ref * 0.05, f['num'], ha='center', fontsize=12, color='g') fl = self.tfl * np.median(s.fl) / np.median(self.tfl) self.artists['template'].set_data(self.twa, fl) if not self.opt.ticklabels: for t in self.artists['ticklabels']: t.set_visible(False) barak.spec.plotatmos(a) self.fig.canvas.draw()
def initvelplot(wa, nfl, ner, nco, transitions, z, fig, atom, ncol, vmin=-1000., vmax=1000., nmodels=0, osc=False, residuals=False): """ Vertical stacked plots of expected positions of absorption lines at the given redshift on a velocity scale.""" colours = ('b', 'r', 'g', 'orangered', 'c', 'purple') ions = [tr['name'].split()[0] for tr in transitions] # want an ordered set ionset = [] for ion in ions: if ion not in ionset: ionset.append(ion) colour = dict(zip(ionset, colours * (len(ions) // len(colours) + 1))) zp1 = z + 1 betamin = vmin / c_kms betamax = vmax / c_kms fig.subplots_adjust(wspace=0.0001, left=0.03, right=0.97, top=0.95, bottom=0.07) axes = [] for i in range(ncol): axes.append(pl.subplot(1, ncol, i + 1)) axes = axes[::-1] for ax in axes: ax.set_autoscale_on(0) # plot top down, so we need reversed() offsets = [] artists = dict(fl=[], er=[], co=[], resid=[], text=[], model=[], models={}, ew=None, regions=[], ticklabels=[], ticks=[], aod=[]) num_per_panel = int(ceil(1 / float(ncol) * len(transitions))) for i, trans in enumerate(reversed(transitions)): tr_id = trans['name'], tuple(trans['tr']) iax, ioff = divmod(i, num_per_panel) ax = axes[iax] ion = trans['name'].split()[0] offset = ioff * 1.5 #print i, offset offsets.append(offset) watrans = trans['wa'] obswa = watrans * zp1 wmin = obswa * (1 + 3 * betamin) wmax = obswa * (1 + 3 * betamax) cond = between(wa, wmin, wmax) #good = ~np.isnan(fl) & (er > 0) & ~np.isnan(co) fl = nfl[cond] #er = ner[cond] co = nco[cond] vel = (wa[cond] / obswa - 1) * c_kms #import pdb; pdb.set_trace() ax.axhline(offset, color='gray', lw=0.5) #artists['er'].extend( # ax.plot(vel, er + offset, lw=1, color='orange', alpha=0.5) ) artists['fl'].extend( ax.plot(vel, fl + offset, color=colour[ion], lw=0.5, ls='steps-mid')) artists['co'].extend( ax.plot(vel, co + offset, color='gray', lw=0.5, ls='dashed')) artists['model'].extend(ax.plot(vel, co + offset, 'k', lw=1, zorder=12)) artists['models'][tr_id] = {} if residuals: artists['resid'].extend( ax.plot([], [], '.', ms=3, mew=0, color='forestgreen')) #ax.axhline(offset-0.1, color='k', lw=0.3) ax.axhline(offset - 0.05, color='k', lw=0.3) ax.axhline(offset - 0.15, color='k', lw=0.3) bbox = dict(facecolor='k', edgecolor='None') transf = mtransforms.blended_transform_factory(ax.transAxes, ax.transData) name = trans['name'] #import pdb; pdb.set_trace() if name.startswith('HI'): ind = indexnear(HIwavs, trans['wa']) lynum = len(HIwavs) - ind name = 'Ly' + str(lynum) + ' ' + name[2:] # find Ly transition number if 'tr' in trans and osc: name = name + ' %.3g' % trans['tr']['osc'] artists['text'].append( ax.text( 0.03, offset + 0.5, name, fontsize=15, #bbox=bbox, transform=transf, zorder=20)) for ax in axes: ax.axvline(0, color='k', lw=0.5, zorder=20) ax.set_xlim(vmin, vmax) ax.set_ylim(-0.5, num_per_panel * 1.5) ax.set_yticks([]) ax.set_xlabel(r'$\Delta v\ \mathrm{(km/s)}$', fontsize=16) artists['title'] = pl.suptitle('$z = %.5f$' % z, fontsize=18) artists['sky'] = [] return artists, np.array(offsets[:num_per_panel]), num_per_panel, axes
def on_keypress(self, event): """ Process a keypress event. """ if event.key == 'S': pl.savefig('junk.png', dpi=300) elif event.key == '?': print help elif event.key == 'T': if self.opt.ticklabels: for t in self.artists['ticklabels']: t.set_visible(False) self.opt.ticklabels = False else: self.opt.ticklabels = True for t in self.artists['ticklabels']: t.set_visible(True) self.fig.canvas.draw() elif event.key == 'R': self.refresh_f26() self.update_model() if self.opt.f26 is not None: self.convolve_LSF() self.apply_zero_offsets() self.apply_cont_adjustments() self.update(self.z) elif event.key == 'i': for ax in self.axes: v0, v1 = ax.get_xlim() ax.set_xlim(0.66 * v0, 0.66 * v1) self.fig.canvas.draw() elif event.key == 'o': for ax in self.axes: v0, v1 = ax.get_xlim() ax.set_xlim(1.33 * v0, 1.33 * v1) self.fig.canvas.draw() elif event.key == 'y': self.ymult *= 1.33 self.update(self.z) elif event.key == 'Y': self.ymult = 1 self.update(self.z) elif event.key == ' ' and event.inaxes is not None: z = self.z # get new redshift dz = (event.xdata / c_kms) * (1 + z) # and new axis limits, if any vmin, vmax = event.inaxes.get_xlim() self.vmin = min(0, vmin) self.vmax = max(0, vmax) self.update(z + dz) if event.key == 'z': c = raw_input('Enter redshift: ') self.update(float(c)) if event.key in 'blepH': i = self.offsets.searchsorted(event.ydata) if i == 0: i = len(self.opt.linelist) off = self.offsets[i - 1] iax = self.axes.index(event.inaxes) i += iax * self.num_per_panel #if event.inaxes == self.axes[1]: # i += self.num_per_panel tr = self.opt.linelist[-i] z = (1 + event.xdata / c_kms) * (1 + self.z) - 1 wa = tr['wa'] * (1 + z) ind = indexnear(self.wa, wa) #print 'transition', tr['name'], tr['wa'], wa if event.key == 'b': # print fitting region if self.prev_keypress == 'b' and self.prev_wa is not None: wmin = self.prev_wa wmax = wa if wmin > wmax: wmin, wmax = wmax, wmin vsig = 6.38 if isinstance(self.opt.Rfwhm, float): vsig = self.opt.Rfwhm / 2.35 print '%%%% %s 1 %.3f %.3f vsig=%.3f' % (self.filename, wmin, wmax, vsig) self.prev_keypress = None self.prev_wa = None else: self.prev_wa = wa elif event.key == 'p': s = '' if self.opt.f26 is not None: i = indexnear(self.allticks.wa, wa) tick = self.allticks[i] s = '\nclosest tick: %-s %.1f z=%.5f' % ( tick['name'], tick['wa0'], tick['z']) print '%12s dv=%.1f wa=%.3f zlya=%.4f, zlyb=%.4f, zlyg=%.4f' % ( tr['name'], event.xdata, wa, wa / wlya - 1, wa / wlyb - 1, wa / wlyg - 1) + s elif event.key == 'l': # guess a line N, z and b and print to screen need to know # which transition we want, and what the central index is. ner = self.ner[ind - 1:ind + 1] nfl = self.nfl[ind - 1:ind + 1] c0 = (ner > 0) & ~np.isnan(nfl) if not c0.sum(): print 'No good pixels!' return f = np.median(nfl[c0]) e = np.median(ner[c0]) if f < e: f = e elif f > 1 - e: f = 1 - e tau0 = -np.log(f) logN, b = guess_logN_b(tr['name'].split()[0], tr['wa'], tr['tr'][1], tau0) print '%-6s %8.6f 0.0 %4.1f 0.0 %4.1f 0.0' % ( tr['name'].split()[0], z, b, logN) elif event.key == 'H': # same as 'l' but always HI ner = self.ner[ind - 1:ind + 1] nfl = self.nfl[ind - 1:ind + 1] c0 = (ner > 0) & ~np.isnan(nfl) if not c0.sum(): print 'No good pixels!' return f = np.median(nfl[c0]) e = np.median(ner[c0]) if f < e: f = e elif f > 1 - e: f = 1 - e tau0 = -np.log(f) logN, b = guess_logN_b('HI', 1215.6701, 0.416400, tau0) redshift = wa / 1215.6701 - 1. print '%-6s %8.6f 0.0 %4.1f 0.0 %4.1f 0.0' % ('HI', redshift, b, logN) elif event.key == 'e': wa = self.wa if self.indprev is not None: i0, i1 = self.indprev, ind if i0 > i1: i0, i1 = i1, i0 f = calc_Wr(i0, i1, wa, tr['tr'], self.ew, self.ewer) print '%s z=%.6f Wr=%.3f+/-%.3fA ngoodpix=%3i wa=%.3f %.3f v=%.1f-%.1f' % ( tr['name'], self.z, f.Wr, f.Wre, f.ngoodpix, wa[i0], wa[i1], self.xprev, event.xdata) print ' Opt. thin approx: logN=%.4f (%.3f-%.3f) 1sig detect lim %.4f' % ( f.logN[1], f.logN[0], f.logN[2], f.Ndetlim) # Assume continuum error of 0.5 sigma, zero point error # of 0.5 sigma. logNlo, logN, logNhi, saturated = calc_N_AOD( self.wa[i0:i1], self.nfl[i0:i1], self.ner[i0:i1], tr['tr']['wa'], tr['tr']['osc'], colo_nsig=0.05, cohi=0.05, #colo_nsig=0.5, cohi_nsig=0.5, #zerolo_nsig=0.5, zerohi_nsig=0.5, zerolo_nsig=1, zerohi_nsig=1, ) s = ' AOD: logN=%.4f %.3f %.3f' % (logN, logN - logNlo, logNhi - logN) if saturated: s += ' Saturated' print s self.artists['ew'].remove() self.artists['ew'] = event.inaxes.fill_between( (wa[i0:i1 + 1] / tr['wa'] / (1 + self.z) - 1) * c_kms, self.ymult * (self.nfl[i0:i1 + 1] - 1) + 1 + off, y2=off + 1, color='r', alpha=0.5) pl.draw() self.indprev = None self.xprev = None return else: if self.artists['ew'] is not None: self.artists['ew'].remove() vpos = [(wa[ind] / tr['wa'] / (1 + self.z) - 1) * c_kms] * 2 #print tr, [off, off+1], vpos self.artists['ew'], = event.inaxes.plot(vpos, [off, off + 1], 'k', alpha=0.3) pl.draw() self.indprev = ind self.xprev = event.xdata elif event.key == 'P': # save redshift, logN, and plot. f = self.filename.rsplit('.', 1) f = f[0] + '_z%.4f.' % self.z + f[1] print "printing to", f pl.savefig(f) elif event.key == 's': c = raw_input('New FWHM in pixels of Gaussian to convolve with? ' '(blank for no smoothing) ') if c == '': # restore spectrum self.smoothby = 1 else: try: fwhm = float(c) except TypeError: print 'FWHM must be a float' if fwhm < 1: self.smoothby = 1 else: self.smoothby = fwhm self.update(self.z) self.prev_keypress = event.key
if 1: ################################################################## # plot the predicted column densities as a function of NHI, and # compare to observed values for the maximum likelihood model ################################################################## # for solar abundances, plotting vs logU/lognH # OVI, CaI, AlI, FeI are very low (logN = 9-10) # SiIV, CIV consistent with upper limits. imax = where(prob == prob.max()) nHbest = nH[imax[1][0]] iZ = indexnear(M.Z, Z[imax[2][0]]) inH = indexnear(M.nH, nH[imax[1][0]]) #iNHI = indexnear(M.NHI, 19.5) iNHI = indexnear(M.NHI, NHI[imax[0][0]]) pl.rc('font', size=14) pl.rc('legend', fontsize=10.5) if 0: trans1 = ('FeII MgI MgII OI OVI NI NII').split() fig = pl.figure(figsize=(4.3, 6)) fig.subplots_adjust(right=0.97, top=0.92,bottom=0.09) ax = pl.subplot(111) plot_trans_vs_U(iZ, iNHI, M, trans1, ax)
def on_keypress(self, event): """ Process a keypress event. """ if event.key == 'S': pl.savefig('junk.png', dpi=300) elif event.key == 'f5': if self.opt.ticklabels: for t in self.artists['ticklabels']: t.set_visible(False) self.opt.ticklabels = False else: self.opt.ticklabels = True for t in self.artists['ticklabels']: t.set_visible(True) self.fig.canvas.draw() elif event.key == 'R': self.refresh_f26() self.update_model() if self.opt.f26 is not None: self.convolve_LSF() self.apply_zero_offsets() self.apply_cont_adjustments() self.update(self.z) elif event.key == ' ' and event.inaxes is not None: z = self.z # get new redshift dz = (event.xdata / c_kms) * (1 + z) # and new axis limits, if any vmin, vmax = event.inaxes.get_xlim() self.vmin = min(0, vmin) self.vmax = max(0, vmax) self.update(z + dz) if event.key == 'z': c = raw_input('Enter redshift: ') self.update(float(c)) if event.key in 'blepH': i = self.offsets.searchsorted(event.ydata) if i == 0: i = len(self.opt.linelist) off = self.offsets[i - 1] if event.inaxes == self.axes[1]: i += self.num_per_panel tr = self.opt.linelist[-i] z = (1 + event.xdata / c_kms) * (1 + self.z) - 1 wa = tr['wa'] * (1 + z) ind = indexnear(self.wa, wa) #print 'transition', tr['name'], tr['wa'], wa if event.key == 'b': # print fitting region if self.prev_keypress == 'b' and self.prev_wa is not None: wmin = self.prev_wa wmax = wa if wmin > wmax: wmin, wmax = wmax, wmin vsig = 6.38 if isinstance(self.opt.Rfwhm, float): vsig = self.opt.Rfwhm / 2.35 print '%%%% %s 1 %.3f %.3f vsig=%.3f' % ( self.filename, wmin, wmax, vsig) self.prev_keypress = None self.prev_wa = None else: self.prev_wa = wa elif event.key == 'p': s = '' if self.opt.f26 is not None: i = indexnear(self.allticks.wa, wa) tick = self.allticks[i] s = '\nclosest tick: %-s %.1f z=%.5f' % ( tick['name'], tick['wa0'], tick['z']) print '%12s dv=%.1f wa=%.3f zlya=%.4f, zlyb=%.4f, zlyg=%.4f' % ( tr['name'], event.xdata, wa, wa/wlya-1, wa/wlyb-1, wa/wlyg-1) + s elif event.key == 'l': # guess a line N, z and b and print to screen need to know # which transition we want, and what the central index is. ner = self.ner[ind - 1:ind + 1] nfl = self.nfl[ind - 1:ind + 1] c0 = (ner > 0) & ~np.isnan(nfl) if not c0.sum(): print 'No good pixels!' return f = np.median(nfl[c0]) e = np.median(ner[c0]) if f < e: f = e elif f > 1 - e: f = 1 - e tau0 = -np.log(f) logN, b = guess_logN_b(tr['name'].split()[0], tr['wa'], tr['tr'][1], tau0) print '%-6s %8.6f 0.0 %4.1f 0.0 %4.1f 0.0' % ( tr['name'].split()[0], z, b, logN) elif event.key == 'H': # same as 'l' but always HI ner = self.ner[ind - 1:ind + 1] nfl = self.nfl[ind - 1:ind + 1] c0 = (ner > 0) & ~np.isnan(nfl) if not c0.sum(): print 'No good pixels!' return f = np.median(nfl[c0]) e = np.median(ner[c0]) if f < e: f = e elif f > 1 - e: f = 1 - e tau0 = -np.log(f) logN, b = guess_logN_b('HI', 1215.6701, 0.416400, tau0) redshift = wa / 1215.6701 - 1. print '%-6s %8.6f 0.0 %4.1f 0.0 %4.1f 0.0' % ('HI', redshift, b, logN) elif event.key == 'e': wa = self.wa if self.indprev is not None: i0, i1 = self.indprev, ind if i0 > i1: i0, i1 = i1, i0 f = calc_Wr(i0, i1, wa, tr['tr'], self.ew, self.ewer) print '%s z=%.6f Wr=%.3f+/-%.3fA ngoodpix=%3i wa=%.3f-%.3f ' % ( tr['name'], f.zp1-1, f.Wr, f.Wre, f.ngoodpix, wa[i0], wa[i1]) print ' Optically thin approx: logN=%.4f (%.3f-%.3f) 5sig detect lim %.4f' % ( f.logN[1], f.logN[0], f.logN[2], f.Ndetlim) # Assume continuum error of 2 sigma, zero point error # of two sigma. Currently this is done per pixel, # would be better to do it per region. No problem as # long as error doesn't vary much over the region. logNlo, logN, logNhi, saturated = calc_N_AOD( self.wa[i0:i1], self.nfl[i0:i1], self.ner[i0:i1], 2, 2, 1, 1, tr['tr']['wa'], tr['tr']['osc']) print ' AOD: logN=%.4f (%.3f-%.3f) Saturated? %s' % ( logN, logNlo, logNhi, saturated) self.artists['ew'].remove() self.artists['ew'] = event.inaxes.fill_between( (wa[i0:i1 + 1] / tr['wa'] / (1 + self.z) - 1) * c_kms, self.nfl[i0:i1 + 1] + off, y2=off + 1, color='r', alpha=0.5) pl.draw() self.indprev = None return else: if self.artists['ew'] is not None: self.artists['ew'].remove() vpos = [(wa[ind] / tr['wa'] / (1 + self.z) - 1) * c_kms] * 2 #print tr, [off, off+1], vpos self.artists['ew'], = event.inaxes.plot( vpos, [off, off + 1], 'k', alpha=0.3) pl.draw() self.indprev = ind elif event.key == 'P': # save redshift, logN, and plot. f = self.filename.rsplit('.', 1) f = f[0] + '_z%.4f.' % self.z + f[1] print "printing to", f pl.savefig(f) elif event.key == 's': c = raw_input('New FWHM in pixels of Gaussian to convolve with? ' '(blank for no smoothing) ') if c == '': # restore spectrum self.smoothby = 1 else: try: fwhm = float(c) except TypeError: print 'FWHM must be a float' if fwhm < 1: self.smoothby = 1 else: self.smoothby = fwhm self.update(self.z) self.prev_keypress = event.key
def on_keypress_custom(self, event): if event.key == 'right': if self.i == self.n - 1: print 'At the last spectrum.' return self.artists['zlines'] = [] self.get_new_spec(self.i + 1) self.update() elif event.key == 'left': if self.i == 0: print 'At the first spectrum.' return self.artists['zlines'] = [] self.get_new_spec(self.i - 1) self.update() elif event.key == '?': print help elif event.key == 'T': if self.opt.ticklabels: for t in self.artists['ticklabels']: t.set_visible(False) self.opt.ticklabels = False else: self.opt.ticklabels = True x0, x1 = self.ax.get_xlim() for t in self.artists['ticklabels']: if x0 < t.get_position()[0] < x1: t.set_visible(True) self.fig.canvas.draw() elif event.key == ' ' and event.inaxes is not None: print '%.4f %.4f %i' % ( event.xdata, event.ydata, indexnear(self.spec[self.i].wa, event.xdata)) elif event.key == 'm' and event.inaxes is not None: if self.wlim1 is not None: self.artists['mlines'].append(plt.gca().axvline( event.xdata, color='k', alpha=0.3)) plt.draw() w0, w1 = self.wlim1, event.xdata if w0 > w1: w0, w1 = w1, w0 sp = self.spec[self.i] good = between(sp.wa, w0, w1) & (sp.er > 0) & ~np.isnan(sp.fl) fmt1 = 'Median flux {:.3g}, rms {:.2g}, er {:.2g}. {:.2g} A/pix' fmt2 = ('SNR {:.2g}/pix, {:.2g}/A (RMS), {:.2g}/pix, {:.2g}/A ' '(er)') if good.sum() < 2: print 'Too few good pixels in range' self.wlim1 = None return medfl = np.median(sp.fl[good]) stdfl = sp.fl[good].std() meder = np.median(sp.er[good]) pixwidth = np.mean(sp.wa[good][1:] - sp.wa[good][:-1]) mult = sqrt(1. / pixwidth) snr1 = medfl / stdfl snr2 = medfl / meder print fmt1.format(medfl, stdfl, meder, pixwidth) print fmt2.format(snr1, snr1 * mult, snr2, snr2 * mult) self.wlim1 = None else: for l in self.artists['mlines']: try: l.remove() except ValueError: # plot has been removed pass self.artists['mlines'].append(plt.gca().axvline( event.xdata, color='k', alpha=0.3)) plt.draw() self.wlim1 = event.xdata print "press 'm' again..." elif event.key == 'C': # fit dodgy continuum sp = self.spec[self.i] co = barak.spec.find_cont(sp.fl) temp, = plt.gca().plot(sp.wa, co, 'm') plt.draw() c = raw_input('Accept continuum? (y) ') if (c + ' ').lower()[0] != 'n': print 'Accepted' sp.co = co self.update() else: temp.remove() elif event.key == 'B' and event.inaxes is not None: # print fitting region wa = event.xdata if self.prev_wa != None: wmin = self.prev_wa wmax = wa if wmin > wmax: wmin, wmax = wmax, wmin print '%%%% %s 1 %.3f %.3f vsig=x.x' % (self.filenames[self.i], wmin, wmax) self.prev_wa = None else: self.prev_wa = wa elif event.key == 'h' and event.inaxes is not None: # print HI line wa = event.xdata z = wa / 1215.6701 - 1 print '%-6s %8.6f 0.0 %3.0f 0.0 %4.1f 0.0' % ('HI', z, 20, 14.0) elif event.key == 'E': # overplot a template c = '0' while c not in '1234': c = raw_input("""\ 1: LBG 2: QSO 3: LRG 4: Starburst galaxy """) temp = get_SEDs('LBG', 'lbg_em.dat') temp.redshift_to(self.zp1 - 1) self.twa = temp.wa self.tfl = temp.fl self.update()
def initvelplot(wa, nfl, ner, nco, transitions, z, fig, atom, ncol, vmin=-1000., vmax=1000., nmodels=0, osc=False, residuals=False): """ Vertical stacked plots of expected positions of absorption lines at the given redshift on a velocity scale.""" colours = ('b', 'r', 'g', 'orangered', 'c', 'purple') ions = [tr['name'].split()[0] for tr in transitions] # want an ordered set ionset = [] for ion in ions: if ion not in ionset: ionset.append(ion) colour = dict(zip(ionset, colours * (len(ions) // len(colours) + 1))) zp1 = z + 1 betamin = vmin / c_kms betamax = vmax / c_kms fig.subplots_adjust(wspace=0.0001, left=0.03, right=0.97, top=0.95, bottom=0.07) axes = [] for i in range(ncol): axes.append(pl.subplot(1, ncol, i+1)) axes = axes[::-1] for ax in axes: ax.set_autoscale_on(0) # plot top down, so we need reversed() offsets = [] artists = dict(fl=[], er=[], co=[], resid=[], text=[], model=[], models={}, ew=None, regions=[], ticklabels=[], ticks=[], aod=[]) num_per_panel = int(ceil(1/float(ncol) * len(transitions))) for i, trans in enumerate(reversed(transitions)): tr_id = trans['name'], tuple(trans['tr']) iax, ioff = divmod(i, num_per_panel) ax = axes[iax] ion = trans['name'].split()[0] offset = ioff * 1.5 #print i, offset offsets.append(offset) watrans = trans['wa'] obswa = watrans * zp1 wmin = obswa * (1 + 3 * betamin) wmax = obswa * (1 + 3 * betamax) cond = between(wa, wmin, wmax) #good = ~np.isnan(fl) & (er > 0) & ~np.isnan(co) fl = nfl[cond] #er = ner[cond] co = nco[cond] vel = (wa[cond] / obswa - 1) * c_kms #import pdb; pdb.set_trace() ax.axhline(offset, color='gray', lw=0.5) #artists['er'].extend( # ax.plot(vel, er + offset, lw=1, color='orange', alpha=0.5) ) artists['fl'].extend( ax.plot(vel, fl + offset, color=colour[ion], lw=0.5, ls='steps-mid')) artists['co'].extend( ax.plot(vel, co + offset, color='gray', lw=0.5, ls='dashed')) artists['model'].extend( ax.plot(vel, co + offset, 'k', lw=1, zorder=12)) artists['models'][tr_id] = {} if residuals: artists['resid'].extend( ax.plot([], [], '.', ms=3, mew=0, color='forestgreen')) #ax.axhline(offset-0.1, color='k', lw=0.3) ax.axhline(offset - 0.05, color='k', lw=0.3) ax.axhline(offset - 0.15, color='k', lw=0.3) bbox = dict(facecolor='k', edgecolor='None') transf = mtransforms.blended_transform_factory( ax.transAxes, ax.transData) name = trans['name'] #import pdb; pdb.set_trace() if name.startswith('HI'): ind = indexnear(HIwavs, trans['wa']) lynum = len(HIwavs) - ind name = 'Ly' + str(lynum) + ' ' + name[2:] # find Ly transition number if 'tr' in trans and osc: name = name + ' %.3g' % trans['tr']['osc'] artists['text'].append( ax.text(0.03, offset + 0.5, name, fontsize=15, #bbox=bbox, transform=transf, zorder=20)) for ax in axes: ax.axvline(0, color='k', lw=0.5, zorder=20) ax.set_xlim(vmin, vmax) ax.set_ylim(-0.5, num_per_panel * 1.5) ax.set_yticks([]) ax.set_xlabel(r'$\Delta v\ \mathrm{(km/s)}$', fontsize=16) artists['title'] = pl.suptitle('$z = %.5f$' % z, fontsize=18) artists['sky'] = [] return artists, np.array(offsets[:num_per_panel]), num_per_panel, axes
def on_keypress_custom(self, event): if event.key == 'pagedown': if self.i == self.n - 1: print('At the last spectrum.') return self.artists['zlines'] = [] self.get_new_spec(self.i + 1) self.update() elif event.key == 'pageup': if self.i == 0: print('At the first spectrum.') return self.artists['zlines'] = [] self.get_new_spec(self.i - 1) self.update() elif event.key == '?': print(help) elif event.key == 'T': if self.opt.ticklabels: for t in self.artists['ticklabels']: t.set_visible(False) self.opt.ticklabels = False else: self.opt.ticklabels = True x0, x1 = self.ax.get_xlim() for t in self.artists['ticklabels']: if x0 < t.get_position()[0] < x1: t.set_visible(True) self.fig.canvas.draw() elif event.key == ' ' and event.inaxes is not None: print('%.4f %.4f %i' % ( event.xdata, event.ydata, indexnear(self.spec[self.i].wa, event.xdata))) elif event.key == 'm' and event.inaxes is not None: if self.wlim1 is not None: self.artists['mlines'].append(plt.gca().axvline( event.xdata, color='k', alpha=0.3)) plt.draw() w0, w1 = self.wlim1, event.xdata if w0 > w1: w0, w1 = w1, w0 sp = self.spec[self.i] good = between(sp.wa, w0, w1) & (sp.er > 0) & ~np.isnan(sp.fl) fmt1 = 'Median flux {:.3g}, rms {:.2g}, er {:.2g}. {:.2g} A/pix' fmt2 = ('SNR {:.3g}/pix, {:.3g}/A (RMS), {:.3g}/pix, {:.3g}/A ' '(er)') if good.sum() < 2: print('Too few good pixels in range') self.wlim1 = None return medfl = np.median(sp.fl[good]) stdfl = sp.fl[good].std() meder = np.median(sp.er[good]) pixwidth = np.mean(sp.wa[good][1:] - sp.wa[good][:-1]) mult = sqrt(1. / pixwidth) snr1 = medfl / stdfl snr2 = medfl / meder print(fmt1.format(medfl, stdfl, meder, pixwidth)) print(fmt2.format(snr1, snr1 * mult, snr2, snr2 * mult)) self.wlim1 = None else: for l in self.artists['mlines']: try: l.remove() except ValueError: # plot has been removed pass self.artists['mlines'].append(plt.gca().axvline( event.xdata, color='k', alpha=0.3)) plt.draw() self.wlim1 = event.xdata print("press 'm' again...") elif event.key == 'C': # fit dodgy continuum sp = self.spec[self.i] co = barak.spec.find_cont(sp.fl) temp, = plt.gca().plot(sp.wa, co, 'm') plt.draw() c = raw_input('Accept continuum? (y) ') if (c + ' ').lower()[0] != 'n': print('Accepted') sp.co = co self.update() else: temp.remove() elif event.key == 'B' and event.inaxes is not None: # print fitting region wa = event.xdata if self.prev_wa != None: wmin = self.prev_wa wmax = wa if wmin > wmax: wmin, wmax = wmax, wmin print('%%%% %s 1 %.3f %.3f vsig=x.x' % ( self.filenames[self.i], wmin, wmax)) self.prev_wa = None else: self.prev_wa = wa elif event.key == 'h' and event.inaxes is not None: # print HI line wa = event.xdata z = wa / 1215.6701 - 1 print('%-6s %8.6f 0.0 %3.0f 0.0 %4.1f 0.0' % ('HI', z, 20, 14.0)) elif event.key == 'E': # overplot a template c = '0' while c not in '1234': c = raw_input("""\ 1: LBG 2: QSO 3: LRG 4: Starburst galaxy """) temp = get_SEDs('LBG', 'lbg_em.dat') temp.redshift_to(self.zp1 - 1) self.twa = temp.wa self.tfl = temp.fl self.update() elif event.key == ')': self.ax.set_xlabel('$\mathrm{Wavelength\ (\AA)}$') self.ax.set_ylabel('$F_\lambda\ \mathrm{(arbitrary)}$') self.update()
def update(self): i = self.i self.artists['mlines'] = [] a = self.ax s = self.spec[i] wa, fl, er, co = s.wa, s.fl, s.er, s.co if self.models[i] is not None and (co > 0).any(): if 'norm' in self.opt and self.opt.norm: temp = self.models[i] else: temp = co * self.models[i] a.plot(wa, temp, color='k') #a.set_title(self.filenames[i]) if self.zp1 is not None: self.update_lines() if self.ticks is not None: if not np.isnan(co).all() and not self.opt.co_is_sky: if 'norm' in self.opt and self.opt.norm: f = np.ones_like(self.ticks.wa) else: f = np.interp(self.ticks.wa, wa, co) else: if 'norm' in self.opt and self.opt.norm: f = np.interp(self.ticks.wa, wa, fl/co) else: f = np.interp(self.ticks.wa, wa, fl) if 'norm' in self.opt and self.opt.norm: height = 0.08 else: height = 0.08 * np.percentile(fl, 90) for j, t in enumerate(self.ticks): if self.opt.showticks: T, Tlabels = plot_tick_wa(a, t.wa, f[j], height, t, tickz=self.opt.tickz) self.artists['ticks'].extend(T) self.artists['ticklabels'].extend(Tlabels) if self.opt.f26 is not None and self.opt.f26.regions is not None and \ self.opt.show_regions: f = fl if 'norm' in self.opt and self.opt.norm: f = self.fl / self.co plotregions(a, self.opt.f26.regions.wmin, self.opt.f26.regions.wmax, wa, f) if self.opt.features is not None: f = self.opt.features sortfl = np.sort(fl[er > 0]) ref = sortfl[int(len(sortfl)*0.95)] - sortfl[int(len(sortfl)*0.05)] wedge = np.concatenate([f.wa0, f.wa1]) axvlines(wedge, ax=a, colors='k', alpha=0.7) temp = co[np.array([indexnear(wa, wav) for wav in f.wac])] ymin = temp + ref * 0.1 ymax = ymin + ref * 0.2 a.vlines(f.wac, ymin, ymax, colors='g') for j, f in enumerate(f): a.text(f['wac'], ymax[j] + ref * 0.05, f['num'], ha='center', fontsize=12, color='g') if self.tfl is not None: fl = self.tfl * np.median(s.fl[er > 0]) / np.median(self.tfl) self.artists['template'].set_data(self.twa, fl) if not self.opt.ticklabels: for t in self.artists['ticklabels']: t.set_visible(False) barak.spec.plotatmos(a) self.fig.canvas.draw()