def plot_lc(self, device='/XSERVE', interactive=0, epoch=1, flux=0, gloes=0, symbol=4): '''Plot this light-curve. You can specify a PGPLOT device, the default is an X server. If interactive=1, basic pygplot keybindings are available. If flux=1, plot in flux space. If epoch=1, plot time relative to Tmax. If gloes=1, use GLoEs to smooth the data and produce a model. You can specify the symbol to plot with 'symbol'.''' if flux: flipaxis = 0 else: flipaxis = 1 p = pygplot.Plot(flipyaxis=flipaxis, title='%s %s lightcurve' % (self.parent.name, self.band), xlabel='Epoch (days)', ylabel='mag', font=2, leftpad=0.5) p.lc_inst = self p.epoch = epoch p.flux = flux if self.parent.Tmax is None: Tmax = 0 else: Tmax = self.parent.Tmax if gloes or self.model_type is not None or self.band in self.parent.model._fbands: self.mp = pygplot.Panel(device=device, llcs=[(0.0, 0.2), (0.0, 0.0)], urcs=[(1.0, 1.0), (1.0, 0.2)], justs=[12, 13]) p2 = pygplot.Plot(flipyaxis=flipaxis, xlabel='Epoch (days)', font=2, ylabel='residuals', leftpad=0.5) p2.lc_inst = self else: self.mp = pygplot.Panel(1, 1, device=device) self.mp.add(p) if gloes or self.model_type is not None or self.band in self.parent.model._fbands: self.mp.add(p2) if flux: y = power(10, -0.4 * (self.mag - self.filter.zp)) ey = y * self.e_mag / 1.0857 else: y = self.mag ey = self.e_mag p.point(self.MJD - epoch * Tmax, y, symbol=symbol) p.error(self.MJD - epoch * Tmax, y, dy1=ey) # Order of preference: plot models, else plot splines, else plot # nothing unless we explicitly ask for gloess. if self.band in self.parent.model._fbands: t = arange(-10, 70, 1.0) + Tmax m, em, mask = self.parent.model(self.band, t) m_m, m_em, m_mask = self.parent.model(self.band, self.MJD) x = self.MJD[self.mask * m_mask] if flux and self.parent.model.model_in_mags: p.line(t[mask] - epoch * Tmax, power(10, -0.4 * (m - self.filter.zp))) y = compress(self.mask * m_mask, self.flux - power(10, -0.4 * (m_m - self.filter.zp))) dy = self.e_flux[self.mask * m_mask] elif not flux and not self.parent.model.model_in_mags: p.line(t[mask] - epoch * Tmax, -2.5 * log10(m[mask]) + self.filter.zp) y = compress(self.mask * m_mask, self.mag + 2.5 * log10(m_m) + self.filter.zp) dy = self.e_mag[self.mask * m_mask] elif flux: p.line(t[mask] - epoch * Tmax, m[mask]) y = self.flux[self.mask * m_mask] - m_m[self.mask * m_mask] dy = self.e_flux[self.mask * m_mask] else: p.line(t[mask] - epoch * Tmax, m[mask]) y = self.mag[self.mask * m_mask] - m_m[self.mask * m_mask] dy = self.e_mag[self.mask * m_mask] p2.point(x - epoch * Tmax, y, symbol=symbol) p2.error(x - epoch * Tmax, y, dy1=dy) p2.line([t[0] - epoch * Tmax, t[-1] - epoch * Tmax], [0, 0]) elif gloes or self.model_type is not None: if self.tmin is not None and self.tmax is not None: t = arange(self.tmin, self.tmax + 1, 1.0) else: t = arange(self.MJD[0], self.MJD[-1] + 1, 1.0) self._t = t self._epoch = epoch m, mask = self.eval(t, t_tol=None) m_model, m_mask = self.eval(self.MJD, t_tol=None) if flux: p.line(compress(mask, t - epoch * Tmax), compress(mask, power(10, -0.4 * (m - self.filter.zp)))) if self.tck is not None: p.point(self.tck[0] - epoch*Tmax, power(10, -0.4*(self.eval(self.tck[0], t_tol=None)[0] \ - self.filter.zp)), color='red', symbol=4) x = compress(self.mask * m_mask, self.MJD) y = compress( self.mask * m_mask, self.flux - power(10, -0.4 * (m_model - self.filter.zp))) dy = compress(self.mask * m_mask, self.e_flux) p2.point(x - epoch * Tmax, y, symbol=symbol) p2.error(x - epoch * Tmax, y, dy1=dy) else: p.line(compress(mask, t - epoch * Tmax), compress(mask, m)) if self.tck is not None: p.point(self.tck[0] - epoch * Tmax, self.eval(self.tck[0], t_tol=None)[0], color='red', symbol=4) x = compress(self.mask * m_mask, self.MJD) y = compress(self.mask * m_mask, self.mag - m_model) p2.point(x - epoch * Tmax, y, symbol=symbol) dy = compress(self.mask * m_mask, self.e_mag) p2.error(x - epoch * Tmax, y, dy1=dy) if self.tck is not None: p2.line( array([self.tck[0][0], self.tck[0][-1]]) - epoch * Tmax, [0, 0]) else: p2.line(array([self.MJD[0], self.MJD[-1]]) - epoch * Tmax, [0, 0]) # useful stats: if self.tck is not None: p.label(0.5, 1.03, 'Np = %d Nk = %d s = %.1f r-chi-sq = %.2f' % \ (len(self.mag), len(self.tck[0]), self.s, self.rchisq), reference='relative', fsize=1, just=0.5) else: if self.line.N is not None: N = self.line.N else: N = -1 if self.line.sigma is not None: sigma = self.line.sigma else: sigma = -1 p.label(0.5, 1.03, 'N = %d sigma = %.1f r-chi-sq = %.2f' % \ (N,sigma,self.line.chisq()), reference='relative', fsize=1, just=0.5) self.mp.plot() if len(self.mp.plots) == 2: self.mp.plots[1].xrange = [ self.mp.plots[0].xmin, self.mp.plots[0].xmax ] self.mp.replot() if interactive: self.mp.interact( bindings={ 'a': add_knot, 'd': delete_knot, 'm': move_knot, 's': change_s, 'S': change_s, 'n': change_N, 'N': change_N, 'x': xrange_select, 'b': box_range_select }) self.mp.close() return (self.mp)
def plot_kcorrs(self, device='13/XW', colors=None, symbols=None): '''Plot the k-corrections, both mangled and un-mangled.''' # See what filters we're going to use: bands = list(self.ks.keys()) if len(bands) == 0: return if colors is None: colors = default_colors if symbols is None: symbols = default_symbols eff_wavs = [] for filter in bands: eff_wavs.append(fset[filter].ave_wave) eff_wavs = asarray(eff_wavs) ids = argsort(eff_wavs) bands = [bands[i] for i in ids] minx = Inf maxx = -Inf for b in bands: if b not in colors: colors[b] = 1 if b not in symbols: symbols[b] = 4 minx = min(minx, self.data[b].t.min()) maxx = max(maxx, self.data[b].t.max()) n_plots = len(bands) cols = int(round(sqrt(n_plots))) rows = (n_plots / cols) if n_plots % cols: rows += 1 p = pygplot.Panel(1, n_plots, device=device, aspect=1.0 / 6 * n_plots) for b in bands: x = self.data[b].MJD - self.Tmax days = arange(int(x[0]), int(x[-1]), 1) rest_days = days / (1 + self.z) / self.ks_s k, k_m = list( map( array, kcorr.kcorr(rest_days.tolist(), self.restbands[b], b, self.z, self.EBVgal, 0.0, version=self.k_version))) k_m = equal(k_m, 1) pp = pygplot.Plot(fsize=1, font=2, xlabel='Epoch (days)', leftpad=0.1, rotylab=1, xrange=[minx, maxx]) pp.filter = b pp.inst = self p.add(pp) pp.line(days[k_m], k[k_m], color=colors[b]) pp.point(x[self.ks_mask[b]], self.ks[b][self.ks_mask[b]], symbol=symbols[b], color=colors[b], fillcolor=colors[b], fsize=2) pp.label(0.9, 0.9, b, just=1, vjust=1, reference='relative') p.plots[n_plots / 2].ylabel = 'K-correction' p.plot() p.interact(bindings={'A': plot_mangled_SED}) p.close() return (p)
def plot_sn(self, xrange=None, yrange=None, device=None, title=None, interactive=0, single=0, dm=1, fsize=1.0, linewidth=3, symbols=None, colors=None, relative=0, legend=1, mask=1, label_bad=0, flux=0, epoch=0, **pargs): '''Plot out the supernova data in a nice format. There are several options: - xrange,yrange: specify the ranges to plot as lists [xmin,xmax], [ymin,ymax] - title: optional title - device: which device to use. Useful for output to file - interactive: allows for an interactive plot. - single: plot out as a single (rather than panelled) plot? - dm: offset in magnitudes between the lightcurves (for single plots) - fsize: override the font size used to plot the graphs - linewidth: override the line width - symbols: dictionary of symbols, indexed by band name. - colors: dictionary of colors to use, indexed by band name. - relative: plot only relative magnitudes (normalized to zero)? - legend: do we plot the legend? - mask: Omit plotting masked out data? - label_bad: label the masked data with red x's? ''' if not xrange: xrange = self.xrange if not yrange: yrange = self.yrange if not symbols: symbols = default_symbols if not colors: colors = default_colors if device is None: device = self.device if fsize is None: fsize = 1.0 if linewidth is None: linewidth = 3 # See what filters we're going to use: if self.filter_order is not None: bands = self.filter_order else: bands = list(self.data.keys()) if not single: eff_wavs = [] for filter in bands: eff_wavs.append(fset[filter].ave_wave) eff_wavs = asarray(eff_wavs) ids = argsort(eff_wavs) self.filter_order = [bands[i] for i in ids] else: mins = [] for filter in bands: if getattr(self.data[filter], 'model', None) is not None: mins.append(min(self.data[filter].model)) else: mins.append(min(self.data[filter].mag)) mins = asarray(mins) ids = argsort(mins) self.filter_order = [bands[i] for i in ids] bands = self.filter_order for b in bands: if b not in colors: colors[b] = 1 if b not in symbols: symbols[b] = 4 if relative: if self.data[bands[0]].model is not None: rel_off = min(self.data[bands[0]].model) else: rel_off = min(self.data[bands[0]].mag) else: rel_off = 0 n_plots = len(bands) # SHould we plot the y-axis upside-down? if not flux: flip = 1 ylabel = 'magnitude' else: flip = 0 ylabel = 'relative flux' if not single: cols = int(round(sqrt(n_plots))) rows = (n_plots / cols) if n_plots % cols: rows += 1 self.p = pygplot.Panel(cols, rows, device='/NULL', aspect=1.0 * rows / cols) else: self.p = pygplot.Plot(device='/NULL', title=title, flipyaxis=flip, xrange=xrange, yrange=yrange, fsize=fsize, linewidth=linewidth, width=linewidth, xlabel='Epoch (days)', ylabel=ylabel, **pargs) i = 0 for filter in bands: if not single: pp = pygplot.Plot(device='/NULL', aspect=1.0, flipyaxis=flip, xrange=xrange, yrange=yrange, linewidth=linewidth, font=2, fsize=fsize, width=linewidth, **pargs) # make a reference to the lightcruve we are plotting. pp.lc = self.data[filter] else: pp = self.p if not i and title is None: label = self.name + " " + filter else: label = filter if not single: pp.label(0.8, 0.9, label, reference='relative', color=colors[filter], just=1, fsize=fsize, vjust=1) if mask: x = self.data[filter].MJD[self.data[filter].mask] if not flux: y = self.data[filter].mag[self.data[filter].mask] + \ single*i*dm - relative*rel_off ey = self.data[filter].e_mag[self.data[filter].mask] else: y = self.data[filter].flux[self.data[filter].mask]* \ power(10, -0.4*(single*i*dm-relative*rel_off)) ey = self.data[filter].e_flux[self.data[filter].mask] else: x = self.data[filter].MJD if not flux: y = self.data[filter].mag + single * i * dm - relative * rel_off ey = self.data[filter].e_mag else: y = self.data[filter].flux* \ power(10, -0.4*(single*i*dm-relative*rel_off)) ey = self.data[filter].e_flux # Make the PANIC data stand out #if filter=='Yc' or filter == 'Jc': # size = fsize + 2 #else: # size = fsize + 1 if self.Tmax is None: Tmax = 0 else: Tmax = self.Tmax pp.point(x - Tmax * epoch, y, symbol=symbols[filter], fill=1, fillcolor=colors[filter], size=fsize + 1, label=filter + '+' + str(i * dm)) pp.error(x - Tmax * epoch, y, dy1=ey, length=0, order=1000) if label_bad: gids = equal(self.data[filter].mask, 0) if sometrue(gids): x = self.data[filter].MJD[gids] - Tmax * epoch if not flux: y = self.data[filter].mag[gids] + \ single*i*dm - relative*rel_off else: y = self.data[filter].flux[gids]* \ power(10, -0.4*(single*i*dm-relative*rel_off)) pp.point(x, y, symbol=5, color='red', size=4.0) # Now check to see if there is a model to plot: if self.model.Tmax is not None and filter in self.model._fbands: t = arange(-10, 70, 1.0) + self.Tmax mag, err, gids = self.model(filter, t) if not flux: y = mag + i * single * dm - relative * rel_off else: zp = fset[filter].zp y = power(10, -0.4*(mag - zp + i*single*dm - \ relative*rel_off)) pp.line(compress(gids, t - self.Tmax * epoch), compress(gids, y), color=colors[filter]) elif self.data[filter].tck is not None: tck = self.data[filter].tck t = arange(tck[0][0], tck[0][-1], 1.0) mag, gids = self.data[filter].eval(t, t_tol=-1) if not flux: y = mag + i * single * dm - relative * rel_off else: zp = fset[filter].zp y = power(10, -0.4*(mag - zp + i*single*dm- \ relative*rel_off)) if self.Tmax is None: Tmax = 0 else: Tmax = self.Tmax pp.line(compress(gids, t - Tmax * epoch), compress(gids, y), color=colors[filter]) i = i + 1 if not single: self.p.add(pp) else: if legend: self.p.legend(position='lr', fsize=1.5, bbox=(0, 0)) self.p.label(0.05, 0.05, self.name, reference='relative') self.p.plot() if self.xrange is None and not single: xmin = self.p.plots[0].xmin xmax = self.p.plots[0].xmax for plot in self.p.plots[1:]: xmin = min(plot.xmin, xmin) xmax = max(plot.xmax, xmax) for plot in self.p.plots: plot.xrange = [xmin, xmax] if self.yrange is None and not single: ymin = self.p.plots[0].ymin ymax = self.p.plots[0].ymax for plot in self.p.plots[1:]: if not flux: ymin = max(plot.ymin, ymin) ymax = min(plot.ymax, ymax) else: ymin = min(plot.ymin, ymin) ymax = max(plot.ymax, ymax) for plot in self.p.plots: plot.yrange = [ymin, ymax] self.p.close() self.p.device = device self.p.plot() if interactive: self.p.interact() self.p.close() return (self.p)