def __init__(self, container, has_xerr=False, has_yerr=False, **kws): ''' ''' self.offset = kws.pop('offset', 0) self.annotated = kws.pop('annotate', True) #haunted = kws.pop('haunted', True) NamedErrorbarContainer.__init__(self, container, has_xerr, has_yerr, **kws) #by default the container is self-linked self.linked = [self] #Save copy of original transform markers = self[0] self._original_transform = markers.get_transform() #make the lines pickable if not markers.get_picker(): markers.set_picker(5) #Initialize offset texts ax = markers.axes self.text_trans = btf(ax.transAxes, ax.transData) ytxt = markers.get_ydata().mean() self.annotation = ax.text(1.005, ytxt, '') #transform=self.text_trans ) #shift to the given offset (default 0) self.shift(self.offset)
def __init__(self, *args, **kws): # self.xtrans = kws.pop( 'xtrans', IdentityTransform() ) # self.ytrans = kws.pop( 'ytrans', IdentityTransform() ) self.aux_trans = kws.pop("aux_trans", btf(IdentityTransform(), IdentityTransform())) # embed() SubplotHost.__init__(self, *args, **kws) # self.__class__, self # Initialize the parasite axis self.parasite = self.twin(self.aux_trans) # ax2 is responsible for "top" axis and "right" axis
def __init__(self, *args, **kw): xax = kw.pop("xax", "f") self.xtrans = ReciprocalTransform() # TODO: SEPARATING TRANSFORMS aux_trans = kw.pop("aux_trans", btf(ReciprocalTransform(), IdentityTransform())) DualAxes.__init__(self, *args, aux_trans=aux_trans, **kw) # self.__class__, self if xax.lower().startswith("f"): self.frequency_axis, self.period_axis = self.xaxis, self.parasite.xaxis else: self.period_axis, self.frequency_axis = self.xaxis, self.parasite.xaxis
def __init__(self, artist, offset=(0.,0.), annotate=True, haunted=False, **kws): ''' ''' #Line2D.__init__(self, *line.get_data()) #self.update_from(line) self.ref_art = artist self.offset = np.array(offset) self.ref_point = offset self.annotated = annotate #haunted = self._original_transform = artist.get_transform() #make the lines pickable if not artist.get_picker(): artist.set_picker(fpicker) # #self.ref_art.set_animated(True) #self._draw_on = True #Manage with ConnectionMixin? self.observers = {} self.validators = {} #self.observers_active = True self.cnt = 0 self.vnt = 0 #Initialize offset texts ax = artist.axes if self.annotated: self.text_trans = btf(ax.transAxes, ax.transData) self.ytxt = artist.get_ydata().mean() self.annotation = ax.text(1.005, self.ytxt, '') self.on_changed(self.shift_text) if haunted: self.haunt() #self._locked = np.zeros(2, bool) self._locked_on = np.empty(2) self._locked_on.fill(None) #shift to the given offset (default 0) self.shift(self.offset)
def plot_timestamp_stats(delta_t, t_cyc, title='Timestamp differences', tolerances=None): """ Plots of timestamp differences to check for incorrectly timestamped data points. Plot shows delta_t vs frame number with histogram panel on the right. Integer multiples of the cycle time are also shown, as well as optionally, the interval limits for flagging points. """ from matplotlib.transforms import blended_transform_factory as btf # plot delta_t as TS + histogram plot_props = dict(fmt='ro') hist_props = dict(log=True, bins=100) # 10 millisecond time bins tsp = ts.plot(delta_t, errorbar=plot_props, hist=hist_props, title=title, axes_labels=[r'$N_{frame}$', r'$\Delta t$ (s)'], draggable=False) ax, hax = tsp.fig.axes # Show multiples of t_cyc trans = btf(ax.transAxes, ax.transData) n = round(delta_t.max().item() / t_cyc) + 1 y_off = 0.01 for i in range(1, int(n)): ax.axhline(i * t_cyc, color='g', lw=2, alpha=0.5) ax.text(0.001, i * t_cyc + y_off, r'$%it_{cyc}$' % i, transform=trans) if tolerances is not None: # show selection limits ltol, utol = tolerances y0, y1 = i * t_cyc + ltol, (i + 1) * t_cyc - utol ax.axhline(y0, ls=':', color='royalblue') ax.axhline(y1, ls=':', color='royalblue') ax.set_ylim(0, n * t_cyc) return tsp
def __init__(self, line, **kws): ''' ''' #Line2D.__init__(self, *line.get_data()) #self.update_from(line) self.line = line self.offset = kws.pop('offset', 0) self.annotated = kws.pop('annotate', True) self._original_transform = line.get_transform() #make the lines pickable if not line.get_picker(): line.set_picker(line_picker) #Initialize offset texts ax = line.axes self.text_trans = btf(ax.transAxes, ax.transData) ytxt = line.get_ydata().mean() self.annotation = ax.text(1.005, ytxt, '')
def f(t): s1 = np.sin(2 * np.pi * t) e1 = np.exp(-t) return np.abs(s1 * e1) + .05 t = np.arange(0.0, 5.0, 0.1) s = f(t) nse = rnd.normal(0.0, 0.3, t.shape) * s fig = plt.figure(figsize=(12, 6)) vax = fig.add_subplot(121) hax = fig.add_subplot(122) vax.plot(t, s + nse, '^') vax.vlines(t, [0], s) vax.vlines([1, 2], 0, 1, transform=btf(vax.transData, vax.transAxes), colors='r') vax.set_xlabel('time (s)') vax.set_title('Vertical lines demo') hax.plot(s + nse, t, '^') hax.hlines(t, [0], s, lw=2) hax.set_xlabel('time (s)') hax.set_title('Horizontal lines demo') plt.show()
qres = 10 res = 50 imin = np.empty(res) Q = np.linspace(1e-2, 2, qres) Q = [0.01, 0.02, 0.05, 0.01, 0.2, 0.5, 1, 1.5, 2, 3, 5] # , 7, 10, 20, 50, 100, 200, 500, 1e3, 1e4] Th_crit = np.empty(len(Q)) for j, q in enumerate(Q): ic = InclinationConstraints(q) Th_crit[j] = ic.θ_crit # print(Table(dict(q=ic.q, ic.φmax=φmax))) # linspace not the best choice for hyperbolic relation Φ = ic.φmax * np.sin(np.linspace(0, np.pi / 2, res)) i = np.vectorize(ic.i, 'f')(Φ) # plot ax.plot(np.degrees(i), np.degrees(Φ), '-') # ax.plot(np.sin(i), np.cos(Φ), 'o') # np.degrees( label = 'q=%.3g' % q ax.text(1, np.degrees(Φ[-1]), label, transform=btf(ax.transAxes, ax.transData)) ax.set(xlabel='$i$', ylabel='$\phi$') ax.grid() # ax.legend() #$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
def hist(x, **kws): '''Plot a nice looking histogram. Parameters ---------- x: sequence Values to histogram Keywords -------- axlabels: sequence One or two axis labels (x,y) title: str The figure title show_stats: str; option ('mode',) Show the given statistic of the distribution * Remaining keywords are passed to ax.hist Returns ------- h: tuple bins, values ax: axes ''' show_stats = kws.pop('show_stats', ()) fmt_stats = kws.pop('fmt_stats', None) lbls = kws.pop('axlabels', ()) title = kws.pop('title', '') #ax = ax.plot kws.setdefault('bins', 100) alpha = kws.setdefault('alpha', 0.5) Q = kws.pop('percentile', []) named_quantiles = {25 : 'lower quartile', #https://en.wikipedia.org/wiki/Quantile#Specialized_quantiles 50 : 'median', 75 : 'upper quartile'} #Create figure ax = kws.pop('ax', None) if ax is None: _, ax = plt.subplots(tight_layout=1, figsize=(12,8)) #else: #fig = ax.figure #Plot the histogram h = ax.hist(x, **kws) #Make axis labels and title xlbl = lbls[0] if len(lbls) else '' ylbl = lbls[1] if len(lbls)>1 else 'Counts' ax.set_xlabel(xlbl) ax.set_ylabel(ylbl) ax.set_title(title) ax.grid() #Extra stats #FIXME bad nomenclature if len(show_stats): from matplotlib.transforms import blended_transform_factory as btf stats = {} if 'min' in show_stats: stats['min'] = x.min() if 'max' in show_stats: stats['max'] = x.max() if 'mode' in show_stats: from scipy.stats import mode mr = mode(x) xmode = mr.mode.squeeze() stats['mode'] = xmode if 'mean' in show_stats: stats['mean'] = x.mean() if 'median' in show_stats: Q.append(50) if len(Q): #'percentile' in show_stats: P = np.percentile(x, Q) for p, q in zip(P, Q): name = named_quantiles.get(q, '$p_{%i}$' % q) stats[name] = p if fmt_stats is None: from recipes.string import minfloatfmt fmt_stats = minfloatfmt for key, val in stats.items(): ax.axvline(val, color='r', alpha=alpha, ls='--', lw=2) trans = btf(ax.transData, ax.transAxes) txt = '%s = %s' % (key, fmt_stats(val)) ax.text(val, 1, txt, rotation='vertical', transform=trans, va='top', ha='right') #if 'percentile' in show_stats: #pass return h, ax
def twilight_txt(ax, s, t, **kw): ax.text(t.plot_date, 1, '{} {} SAST'.format(s, local_time_str(t)), rotation=90, ha='right', va='top', transform=btf(ax.transData, ax.transAxes), clip_on=True, **kw)
def setup_figure(self): self.figure = fig = plt.figure(figsize=(18,10)) fig.subplots_adjust(top=0.94, left=0.05, right=0.85, bottom=0.05) #setup axes with self.ax = ax = VizAxes(fig, 111) lon = self.siteloc.longitude sid_trans = get_sid_trans(self.date, lon) aux_trans = btf(sid_trans, IdentityTransform()) ax.parasite = ax.twin(aux_trans) ax.setup_ticks() fig.add_subplot(ax) #horizon line horizon = ax.axhline(0, 0, 1, color='0.85') #Shade twighlight / night for i, twilight in enumerate(zip(self.dusk.items(), self.dawn.items())): desc, times = zip(*twilight) ax.axvspan(*Time(times).plot_date, color=str(0.25*(3-i))) for words, t in zip(desc, times): self.twilight_txt(ax, words, t, color=str(0.33*i)) #Indicate moonrise/set for rise_set, time in self.mooning.items(): ax.axvline(time.plot_date, c='y', ls='--') self.twilight_txt(ax, rise_set, time, color='y') #TODO: enable picking for sun / moon sun_pl, = ax.plot(self.tp, self.sun.alt, 'orangered', ls='none', markevery=2, marker='o', ms=10, label='sun') moon_pl, = ax.plot(self.tp, self.moon.alt, 'yellow', ls='none', markevery=2, marker=self.get_moon_marker(), ms=10, label='moon ({:.0%})'.format(self.moon_ill)) #site / date info text ax.text(0, 1.04, self.date_info_txt(self.midnight), fontweight='bold', ha='left', transform=ax.transAxes) ax.text(1, 1.04, self.obs_info_txt(), fontweight='bold', ha='right', transform=ax.transAxes) #setup axes #dloc = AutoDateLocator() #ax.xaxis.set_major_locator(dloc) #ax.xaxis.set_minor_locator(AutoMinorLocator()) #ax.yaxis.set_minor_locator(AutoMinorLocator()) #ax.yaxis.set_major_formatter(DegreeFormatter()) #ax.xaxis.set_major_formatter(AutoDateFormatter(dloc)) #ax.yaxis.set_minor_formatter(DegreeFormatter()) just_before_sunset = (self.sunset - 0.25*u.h).plot_date just_after_sunrise = (self.sunrise + 0.25*u.h).plot_date ax.set_xlim(just_before_sunset, just_after_sunrise) ax.set_ylim(-10, 90) #which part of the visibility curves are visible within axes self._lt = (just_before_sunset < self.tp) & (self.tp < just_after_sunrise) #labels for axes ax.set_ylabel('Altitude', fontweight='bold') ax.parasite.set_ylabel('Airmass', fontweight='bold') #UTC / SAST #TODO: align with labels instead of guessing coordinates... self.ax.text(1, -0.005, 'SAST', color='g', fontweight='bold', va='top', ha='right', transform=self.ax.transAxes) self.ax.text(1,-0.02, 'UTC', color='k', fontweight='bold', va='top', ha='right', transform=self.ax.transAxes) #sidereal time label txt = self.ax.text(1, 1.01, 'Sid.T.', color='c', fontweight='bold', va = 'bottom', ha='right', transform=self.ax.transAxes) #sun / moon legend leg = self.ax.legend(bbox_to_anchor=(1.05, 0), loc=3, borderaxespad=0., frameon=True) leg.get_frame().set_edgecolor('k') self.ax.add_artist(leg) ax.grid()
from matplotlib.transforms import blended_transform_factory as btf import numpy as np import numpy.random as rnd def f(t): s1 = np.sin(2 * np.pi * t) e1 = np.exp(-t) return np.abs(s1 * e1) + .05 t = np.arange(0.0, 5.0, 0.1) s = f(t) nse = rnd.normal(0.0, 0.3, t.shape) * s fig = plt.figure(figsize=(12, 6)) vax = fig.add_subplot(121) hax = fig.add_subplot(122) vax.plot(t, s + nse, '^') vax.vlines(t, [0], s) vax.vlines([1, 2], 0, 1, transform=btf(vax.transData, vax.transAxes), colors='r') vax.set_xlabel('time (s)') vax.set_title('Vertical lines demo') hax.plot(s + nse, t, '^') hax.hlines(t, [0], s, lw=2) hax.set_xlabel('time (s)') hax.set_title('Horizontal lines demo') plt.show()