Esempio n. 1
0
class Plot:
    def __init__(self):
        self._made = False
        self._data = []
        self._boxes = []
        self._enlarge = (0.02, 0.02, 0.02, 0.02)
        self._grid = True
        self._xscale = 'linear'
        self._yscale = 'linear'
        self._leg = False
        self._xaxis = None
        self._yaxis = None
        self._fitcount = 0

    def xaxis(self, q):
        self._made = False
        if not isinstance(q, Quantity):
            raise TypeError("xaxis argument must be Quantity!")
        self._xaxis = Quantity(q.sprefunit())
        self._xaxis.label = q.label
        self._xaxis.latex = q.latex
        self._xaxis.symbol = q.symbol
        return self

    def yaxis(self, q):
        self._made = False
        if not isinstance(q, Quantity):
            raise TypeError("yaxis argument must be Quantity!")
        self._yaxis = Quantity(q.sprefunit())
        self._yaxis.label = q.label
        self._yaxis.latex = q.latex
        self._yaxis.symbol = q.symbol
        return self

    def makex(self):
        if self._xaxis is None: return ''
        lab = []
        if self._xaxis.label:
            lab.append(self._xaxis.label)
        sl = self._xaxis.latex or self._xaxis.symbol
        if sl:
            lab.append("${}$".format(sl))
        punit = self._xaxis.sprefunit(latex=True)
        if punit:
            lab.append('in ${}$'.format(punit))
        return ' '.join(lab)

    def makey(self):
        if self._yaxis is None: return ''
        lab = []
        if self._yaxis.label:
            lab.append(self._yaxis.label)
        sl = self._yaxis.latex or self._yaxis.symbol
        if sl:
            lab.append("${}$".format(sl))
        punit = self._yaxis.sprefunit(latex=True)
        if punit:
            lab.append('in ${}$'.format(punit))
        return ' '.join(lab)

    """  def xunit(self, s):
    self._made = False
    if self._xaxis is None:
      self._xaxis = Quantity()
    q = Quantity(s)
    self._xaxis.preferredUnit = q.preferredUnit
    self._xaxis.value = q.value
    self._xaxis.uvec = q.uvec
    return self
  def yunit(self, s):
    self._made = False
    if self._yaxis is None:
      self._yaxis = Quantity()
    q = Quantity(s)
    self._yaxis.preferredUnit = q.preferredUnit
    self._yaxis.value = q.value
    self._yaxis.uvec = q.uvec
    return self"""

    def xlabel(self, s, symbol=None, latex=None):
        self._made = False
        if self._xaxis is None:
            self._xaxis = Quantity()
        self._xaxis.label = s
        if symbol is not None: self._xaxis.symbol = symbol
        if latex is not None: self._yaxis.latex = latex
        return self

    def ylabel(self, s):
        self._made = False
        if self._yaxis is None:
            self._yaxis = Quantity()
        self._yaxis.label = s
        if symbol is not None: self._xaxis.symbol = symbol
        if latex is not None: self._yaxis.latex = latex
        return self

    def legend(self, on=True):
        self._made = False
        self._leg = on
        return self

    def data(self, x, y, fmt, errorbar, label=True, **kwds):
        self._made = False
        if label == True:
            kwds['label'] = y.label
        elif label is not None:
            kwds['label'] = label

        self._data.append((x, y, fmt, errorbar, kwds))

        if isinstance(x, Quantity):
            if self._xaxis is None:
                self.xaxis(x)

        if isinstance(y, Quantity):
            if self._yaxis is None:
                self.yaxis(y)
        return self

    def error(self,
              x,
              y,
              fmt='.k',
              markersize=5,
              capsize=0,
              label=True,
              ecolor='0.3',
              **kwds):
        kwds['capsize'] = capsize
        self._made = False
        self.data(x,
                  y,
                  fmt=fmt,
                  markersize=markersize,
                  label=label,
                  ecolor=ecolor,
                  errorbar=True,
                  **kwds)
        return self  # cascade

    def points(self, x, y, fmt='.k', markersize=3, label=True, **kwds):
        self._made = False
        self.data(x,
                  y,
                  fmt=fmt,
                  markersize=markersize,
                  label=label,
                  errorbar=False,
                  **kwds)
        return self  # cascade

    def line(self, x, y, fmt='-b', linewidth=1, label=True, **kwds):
        self._made = False
        self.data(x,
                  y,
                  fmt=fmt,
                  linewidth=linewidth,
                  label=label,
                  errorbar=False,
                  **kwds)
        return self  # cascade

    def histoline(self, x, y, *args, **kwds):
        l = len(x)

        doubledX = np.zeros(2 * l)
        doubledY = np.zeros(2 * l)
        for i in range(0, l):
            doubledY[2 * i] = y.value[i]
            doubledY[2 * i + 1] = y.value[i]

        deltaX = x.value[1] - x.value[0]
        doubledX[0] = x.value[0] - deltaX / 2
        for i in range(0, l - 1):
            doubledX[2 * i + 1] = (x.value[i] + x.value[i + 1]) / 2
            doubledX[2 * i + 2] = (x.value[i] + x.value[i + 1]) / 2
        deltaX = x.value[-1] - x.value[-2]
        doubledX[-1] = x.value[-1] + deltaX / 2

        doubledX = [doubledX[0]] + list(doubledX) + [doubledX[-1]]
        doubledY = [0] + list(doubledY) + [0]

        nx = Quantity(doubledX, 0, x.uvec)
        nx.name(x.label, x.symbol, x.latex)
        nx.preferredUnit = x.preferredUnit
        ny = Quantity(doubledY, 0, y.uvec)
        ny.name(y.label, y.symbol, y.latex)
        ny.preferredUnit = y.preferredUnit

        return self.line(nx, ny, *args, **kwds)

    fitcolors = 'brgcmy'

    def fit(self, mf, box=True, bpos=None, xmin=None, xmax=None, chi2=True):
        if not isinstance(mf, ModelFit):
            raise TypeError(
                "Argument of Plot.fit must be a ModelFit, but {} given.".
                format(type(mf)))

        self._fitcount += 1
        text = 'Fit: ${}$\n\n'.format(mf.eq())
        if mf.sr >= 3:
            text += 'fit failed ({})!\n'.format(mf.sr)
        for p in mf.parameters:
            text += '  ${}$\n'.format(p.tex())
        if chi2:
            text += '  $\chi^2/\mathrm{ndf} = ' + ('{:.2f} / {}$'.format(
                *mf.chi))

        xmin = xmin or min(mf.xo.value)
        xmax = xmax or max(mf.xo.value)

        if box:
            self.box((self._fitcount, text, mf.xo, mf.yo, bpos))
        x = Quantity(np.linspace(xmin, xmax, 200), unit=mf.xo.uvec)
        p0 = [Quantity(p.value, 0, p.uvec) for p in mf.parameters]
        self.line(x,
                  mf.func(x, *p0),
                  fmt='-' + Plot.fitcolors[(self._fitcount - 1) % 6])
        return self

    def box(self, text):
        self._made = False
        self._boxes.append(text)
        return self

    def xlog(self, log=True):
        self._made = False
        self._xscale = 'log' if log else 'linear'
        return self

    def ylog(self, log=True):
        self._made = False
        self._yscale = 'log' if log else 'linear'
        return self

    def save(self, filename, **kwds):
        if not self._made: self.make()
        # dpi not set here anymore
        # do this in a matlibplotrc file, e.g.
        #  figure.dpi     : 300
        plt.tight_layout()
        plt.savefig(filename, **kwds)
        return self

    def show(self):
        if not self._made: self.make()
        plt.show()
        return self

    def make(self, clf=True, fig=None, axes=None):
        if clf: plt.clf()
        if fig is None and axes is None: fig = plt.figure()
        if axes is None: axes = fig.add_subplot(111)

        xlim = None
        ylim = None

        for x, y, fmt, errorbar, d in self._data:
            if isinstance(x, Quantity):
                f = Quantity(unit=x.uvec) / self._xaxis
                if not f.unitless():
                    warnings.warn(
                        'The ratio of x axis unit ({}) and real unit ({}) must be unit less.'
                        .format(self._xaxis.siunit(), y.siunit()))
                f = float(f)
                sx = x.stddev() * f
                x = x.value * f
            else:
                #f = float(1 / Quantity(self._xunit))
                #x  = x * f
                sx = 0

            if isinstance(y, Quantity):
                f = Quantity(unit=y.uvec) / self._yaxis
                if not f.unitless():
                    warnings.warn(
                        'The ratio of preferred unit ({}) and real unit ({}) must be unit less.'
                        .format(self._yaxis.siunit(), y.siunit()))
                f = float(f)
                sy = y.stddev() * f
                y = y.value * f
            else:
                #f = float(1 / Quantity(self.ypreferredUnit))
                #y  = y * f
                sy = 0

            xmin = np.nanmin(x - sx)
            xmax = np.nanmax(x + sx)
            ymin = np.nanmin(y - sy)
            ymax = np.nanmax(y + sy)
            if xlim is None: xlim = [xmin, xmax]
            if ylim is None: ylim = [ymin, ymax]
            xlim[0] = min(xlim[0], xmin)
            xlim[1] = max(xlim[1], xmax)
            ylim[0] = min(ylim[0], ymin)
            ylim[1] = max(ylim[1], ymax)

            xlimraw = xlim
            ylimraw = ylim

            xerr = sx
            yerr = sy

            if errorbar:
                axes.errorbar(x, y, sy, sx, fmt=fmt, **d)
            else:
                axes.plot(x, y, fmt, **d)

        xdif = xlim[1] - xlim[0]
        ydif = ylim[1] - ylim[0]
        xlim[0] -= xdif * self._enlarge[0]
        xlim[1] += xdif * self._enlarge[1]
        ylim[0] -= ydif * self._enlarge[2]
        ylim[1] += ydif * self._enlarge[3]

        i = 0
        taken = [[0] * 2, [0] * 2, [0] * 2]
        for b in self._boxes:
            if isinstance(b, tuple):
                fitnum, b, x, y, bpos = b

            if isinstance(bpos, tuple):
                x = bpos[0] / 3
                y = bpos[1] / 2
            else:
                penalty = []
                for x in range(3):
                    for y in range(2):
                        points = 0
                        total = 0
                        for dx, dy, fmt, errorbar, d in self._data:
                            fx = float(Quantity(unit=dx.uvec) / self._xaxis)
                            fy = float(Quantity(unit=dy.uvec) / self._yaxis)
                            idx1 = (dx.value * fx >
                                    (xlim[0] + xdif * (x / 3 - 0.1)))
                            idx2 = (dx.value * fx <
                                    (xlim[0] + xdif * (x + 1.3) / 3))
                            idx3 = (dy.value * fy >
                                    (ylim[0] + ydif * (y / 2 - 0.1)))
                            idx4 = (dy.value * fy <
                                    (ylim[0] + ydif * (y + 1.2) / 2))
                            idx = idx1 * idx2 * idx3 * idx4
                            points += len(dx.value[idx]) / len(dx.value)
                            total = len(dx.value)
                        points += total * taken[x][y]
                        penalty.append((x, y, points))
                x, y, points = min(penalty, key=lambda y: y[2])
                taken[x][y] += 1

            if y == 0:
                yalign = 'bottom'
                y = ylimraw[0] + ydif * 0.05
            elif y == 1:
                yalign = 'top'
                y = ylimraw[1] - ydif * 0.05

            if x == 0:
                xalign = 'left'
                x = xlimraw[0] + xdif * 0.05
            elif x == 1:
                xalign = 'center'
                x = xlimraw[0] + 0.5 * xdif
            elif x == 2:
                xalign = 'right'
                x = xlimraw[1] - xdif * 0.05

            if self._fitcount > 1 and False:
                b = '({}) {}'.format(fitnum, b)
                fx = Quantity(unit=x.uvec) / self._xaxis
                fy = Quantity(unit=y.uvec) / self._yaxis
                if not fx.unitless():
                    warnings.warn(
                        'The ratio of preferred unit ({}) and real unit ({}) must be unit less.'
                        .format(self._xaxis.siunit(), x.siunit()))
                if not fy.unitless():
                    warnings.warn(
                        'The ratio of preferred unit ({}) and real unit ({}) must be unit less.'
                        .format(self._yaxis.siunit(), y.siunit()))
                fx = float(fx)
                fy = float(fy)
                tx = x.value * fx
                ty = y.value * fy
                tx = (min(tx) + max(tx)) / 2
                ty = max(ty)
                ty += 0.05 * ydif

                axes.text(tx,
                          ty,
                          '({})'.format(fitnum),
                          color=Plot.fitcolors[(fitnum - 1) % 6],
                          horizontalalignment='center',
                          verticalalignment='bottom')

            #plt.figtext(*xy, s=b,bbox=dict(facecolor='w', edgecolor='black', pad=10), multialignment='left', **align)
            axes.annotate(b,
                          xy=(x, y),
                          bbox=dict(facecolor='w', edgecolor='k', pad=10),
                          multialignment='left',
                          horizontalalignment=xalign,
                          verticalalignment=yalign)

        if self._grid: pylab.grid()
        axes.set_xscale(self._xscale)
        axes.set_yscale(self._yscale)
        if self._leg: pylab.legend()

        if self.makex(): axes.set_xlabel(self.makex())
        if self.makey(): axes.set_ylabel(self.makey())

        self._made = True
        axes.set_xlim(*xlimraw)
        axes.set_ylim(*ylimraw)
        return self  # cascade
Esempio n. 2
0
class Plot:

  def __init__(self):
    self._made      = False
    self._data     = []
    self._boxes    = []
    self._enlarge  = (0.02,0.02,0.02,0.02)
    self._grid     = True
    self._xscale   = 'linear'
    self._yscale   = 'linear'
    self._leg      = False
    self._xaxis    = None
    self._yaxis    = None
    self._fitcount = 0

  def xaxis(self, q): 
    self._made = False
    if not isinstance(q, Quantity):
      raise TypeError("xaxis argument must be Quantity!")
    self._xaxis = Quantity(q.sprefunit())
    self._xaxis.label = q.label
    self._xaxis.latex = q.latex
    self._xaxis.symbol = q.symbol
    return self
  def yaxis(self, q): 
    self._made = False
    if not isinstance(q, Quantity):
      raise TypeError("yaxis argument must be Quantity!")
    self._yaxis = Quantity(q.sprefunit())
    self._yaxis.label = q.label
    self._yaxis.latex = q.latex
    self._yaxis.symbol = q.symbol
    return self

  def makex(self):
    if self._xaxis is None: return ''
    lab = []
    if self._xaxis.label:
      lab.append(self._xaxis.label)
    sl = self._xaxis.latex or self._xaxis.symbol
    if sl: 
      lab.append("${}$".format(sl))
    punit = self._xaxis.sprefunit(latex=True)
    if punit:
      lab.append('in ${}$'.format(punit))
    return ' '.join(lab)
  def makey(self):
    if self._yaxis is None: return ''
    lab = []
    if self._yaxis.label:
      lab.append(self._yaxis.label)
    sl = self._yaxis.latex or self._yaxis.symbol
    if sl: 
      lab.append("${}$".format(sl))
    punit = self._yaxis.sprefunit(latex=True)
    if punit:
      lab.append('in ${}$'.format(punit))
    return ' '.join(lab)

  """  def xunit(self, s):
    self._made = False
    if self._xaxis is None:
      self._xaxis = Quantity()
    q = Quantity(s)
    self._xaxis.preferredUnit = q.preferredUnit
    self._xaxis.value = q.value
    self._xaxis.uvec = q.uvec
    return self
  def yunit(self, s):
    self._made = False
    if self._yaxis is None:
      self._yaxis = Quantity()
    q = Quantity(s)
    self._yaxis.preferredUnit = q.preferredUnit
    self._yaxis.value = q.value
    self._yaxis.uvec = q.uvec
    return self"""

  def xlabel(self, s, symbol=None, latex=None): 
    self._made = False
    if self._xaxis is None:
      self._xaxis = Quantity()
    self._xaxis.label = s
    if symbol is not None: self._xaxis.symbol = symbol
    if latex is not None:  self._yaxis.latex  = latex
    return self
  def ylabel(self, s): 
    self._made = False
    if self._yaxis is None:
      self._yaxis = Quantity()
    self._yaxis.label = s
    if symbol is not None: self._xaxis.symbol = symbol
    if latex is not None:  self._yaxis.latex  = latex
    return self

  def legend(self, on=True):
    self._made = False
    self._leg = on
    return self


  def data(self, x, y, fmt, errorbar, label=True, **kwds):
    self._made = False
    if label == True:
      kwds['label']=y.label
    elif label is not None:
      kwds['label']=label


    self._data.append( (x, y, fmt, errorbar, kwds) )
    
    if isinstance(x, Quantity):
      if self._xaxis is None:
        self.xaxis(x)
    
    if isinstance(y, Quantity):
      if self._yaxis is None:
        self.yaxis(y)
    return self

  def error(self, x, y, fmt='.k', markersize=5, capsize=0, label=True, ecolor='0.3', **kwds):
    kwds['capsize'] = capsize
    self._made = False
    self.data(x, y, fmt=fmt, markersize=markersize, label=label, ecolor=ecolor, errorbar=True, **kwds)
    return self # cascade

  def points(self, x, y, fmt='.k', markersize=3, label=True, **kwds):
    self._made = False
    self.data(x, y, fmt=fmt, markersize=markersize, label=label, errorbar=False, **kwds)
    return self # cascade
    
  def line(self, x, y, fmt='-b', linewidth=1, label=True, **kwds):
    self._made = False
    self.data(x, y, fmt=fmt, linewidth=linewidth, label=label, errorbar=False, **kwds)
    return self # cascade

  def histoline(self, x, y, *args, **kwds):
    l = len(x)

    doubledX = np.zeros(2*l)
    doubledY = np.zeros(2*l)
    for i in range(0, l):
      doubledY[2*i]   = y.value[i]
      doubledY[2*i+1] = y.value[i]

    deltaX = x.value[1] - x.value[0]
    doubledX[0] = x.value[0] - deltaX / 2
    for i in range(0, l-1):
      doubledX[2*i+1]   = (x.value[i] + x.value[i+1]) / 2
      doubledX[2*i+2] = (x.value[i] + x.value[i+1]) / 2
    deltaX = x.value[-1] - x.value[-2]
    doubledX[-1] = x.value[-1] + deltaX / 2 

    doubledX = [doubledX[0]] + list(doubledX) + [doubledX[-1]]
    doubledY = [0] + list(doubledY) + [0]

    nx = Quantity(doubledX, 0, x.uvec)
    nx.name(x.label, x.symbol, x.latex)
    nx.preferredUnit = x.preferredUnit
    ny = Quantity(doubledY, 0, y.uvec)
    ny.name(y.label,y.symbol,y.latex)
    ny.preferredUnit = y.preferredUnit
    
    return self.line(nx, ny, *args, **kwds)


  fitcolors = 'brgcmy'

  def fit(self, mf, box=True, bpos=None, xmin=None, xmax=None, chi2=True):
    if not isinstance(mf, ModelFit):
      raise TypeError("Argument of Plot.fit must be a ModelFit, but {} given.".format(type(mf)))

    self._fitcount += 1
    text = 'Fit: ${}$\n\n'.format(mf.eq())
    if mf.sr >= 3:
      text += 'fit failed ({})!\n'.format(mf.sr)
    for p in mf.parameters:
      text += '  ${}$\n'.format(p.tex())
    if chi2:
      text += '  $\chi^2/\mathrm{ndf} = ' +('{:.2f} / {}$'.format(*mf.chi))

    xmin = xmin or min(mf.xo.value)
    xmax = xmax or max(mf.xo.value)

    if box:
      self.box( (self._fitcount, text, mf.xo, mf.yo, bpos) )
    x = Quantity(np.linspace(xmin, xmax, 200), unit=mf.xo.uvec)
    p0 = [Quantity(p.value, 0, p.uvec) for p in mf.parameters]
    self.line(x, mf.func(x, *p0), fmt='-'+Plot.fitcolors[(self._fitcount-1)%6])
    return self


  def box(self, text):
    self._made = False
    self._boxes.append(text)
    return self

  def xlog(self, log=True):
    self._made = False
    self._xscale = 'log' if log else 'linear'
    return self
  
  def ylog(self, log=True):
    self._made = False
    self._yscale = 'log' if log else 'linear'
    return self

  def save(self, filename, **kwds):
    if not self._made: self.make()
    # dpi not set here anymore
    # do this in a matlibplotrc file, e.g.
    #  figure.dpi     : 300 
    plt.tight_layout()
    plt.savefig(filename, **kwds)
    return self
    
  def show(self):
    if not self._made: self.make()
    plt.show()
    return self

  def make(self, clf=True, fig=None, axes=None):
    if clf: plt.clf()
    if fig is None and axes is None: fig = plt.figure()
    if axes is None: axes = fig.add_subplot(111)

    xlim = None
    ylim = None

    for x, y, fmt, errorbar, d in self._data:
      if isinstance(x, Quantity):
        f = Quantity(unit=x.uvec) / self._xaxis
        if not f.unitless():
          warnings.warn('The ratio of x axis unit ({}) and real unit ({}) must be unit less.'.format(self._xaxis.siunit(), y.siunit()))
        f = float(f)
        sx = x.stddev() * f
        x  = x.value * f
      else:
        #f = float(1 / Quantity(self._xunit))
        #x  = x * f
        sx = 0

      if isinstance(y, Quantity):
        f = Quantity(unit=y.uvec) / self._yaxis
        if not f.unitless():
          warnings.warn('The ratio of preferred unit ({}) and real unit ({}) must be unit less.'.format(self._yaxis.siunit(), y.siunit()))
        f = float(f)
        sy = y.stddev() * f
        y  = y.value * f
      else:
        #f = float(1 / Quantity(self.ypreferredUnit))
        #y  = y * f
        sy = 0

      xmin = np.nanmin(x - sx)
      xmax = np.nanmax(x + sx)
      ymin = np.nanmin(y - sy)
      ymax = np.nanmax(y + sy)
      if xlim is None: xlim = [xmin, xmax]
      if ylim is None: ylim = [ymin, ymax]
      xlim[0] = min(xlim[0], xmin)
      xlim[1] = max(xlim[1], xmax)
      ylim[0] = min(ylim[0], ymin)
      ylim[1] = max(ylim[1], ymax)

      xlimraw = xlim
      ylimraw = ylim

      xerr = sx
      yerr = sy

      if errorbar:
        axes.errorbar(x, y, sy, sx, fmt=fmt, **d)
      else:
        axes.plot(x, y, fmt, **d)

    xdif = xlim[1] - xlim[0]
    ydif = ylim[1] - ylim[0]
    xlim[0] -= xdif * self._enlarge[0]
    xlim[1] += xdif * self._enlarge[1]
    ylim[0] -= ydif * self._enlarge[2]
    ylim[1] += ydif * self._enlarge[3]


    i = 0
    taken = [ [0]*2, [0]*2, [0]*2 ]
    for b in self._boxes:
      if isinstance(b, tuple):
        fitnum, b, x, y, bpos = b
        
      if isinstance(bpos, tuple): 
        x = bpos[0] / 3
        y = bpos[1] / 2
      else:
        penalty = []
        for x in range(3):
          for y in range(2):
            points = 0 
            total = 0
            for dx, dy, fmt, errorbar, d in self._data:
              fx = float(Quantity(unit=dx.uvec) / self._xaxis)
              fy = float(Quantity(unit=dy.uvec) / self._yaxis)
              idx1 = (dx.value * fx > (xlim[0] + xdif * (x/3 - 0.1)))
              idx2 = (dx.value * fx < (xlim[0] + xdif * (x+1.3) / 3))
              idx3 = (dy.value * fy > (ylim[0] + ydif * (y/2 - 0.1)))
              idx4 = (dy.value * fy < (ylim[0] + ydif * (y+1.2) / 2))
              idx = idx1 * idx2 * idx3 * idx4
              points += len(dx.value[idx]) / len(dx.value)
              total = len(dx.value)
            points += total * taken[x][y]
            penalty.append( (x, y, points) )
        x, y, points = min(penalty, key=lambda y: y[2])
        taken[x][y] += 1

      if y == 0:
        yalign = 'bottom'
        y = ylimraw[0] + ydif * 0.05
      elif y == 1:
        yalign = 'top'
        y = ylimraw[1] - ydif * 0.05

      if x == 0:
        xalign = 'left'
        x = xlimraw[0] + xdif * 0.05
      elif x == 1:
        xalign = 'center'
        x = xlimraw[0] + 0.5 * xdif
      elif x == 2:
        xalign = 'right'
        x = xlimraw[1] - xdif * 0.05


      if self._fitcount > 1:
        b = '({}) {}'.format(fitnum, b)
        fx = Quantity(unit=x.uvec) / self._xaxis
        fy = Quantity(unit=y.uvec) / self._yaxis
        if not fx.unitless():
          warnings.warn('The ratio of preferred unit ({}) and real unit ({}) must be unit less.'.format(self._xaxis.siunit(), x.siunit()))
        if not fy.unitless():
          warnings.warn('The ratio of preferred unit ({}) and real unit ({}) must be unit less.'.format(self._yaxis.siunit(), y.siunit()))
        fx = float(fx)
        fy = float(fy)
        tx = x.value * fx
        ty = y.value * fy
        tx = (min(tx)+max(tx))/2
        ty = max(ty)
        ty += 0.05 * ydif

        axes.text(tx, ty, '({})'.format(fitnum), color=Plot.fitcolors[(fitnum-1)%6], horizontalalignment='center', verticalalignment='bottom')


      #plt.figtext(*xy, s=b,bbox=dict(facecolor='w', edgecolor='black', pad=10), multialignment='left', **align)
      axes.annotate(b, xy=(x, y), bbox=dict(facecolor='w', edgecolor='k', pad=10), multialignment='left', horizontalalignment=xalign, verticalalignment=yalign)


    if self._grid: pylab.grid()
    axes.set_xscale(self._xscale)
    axes.set_yscale(self._yscale)
    if self._leg: pylab.legend()

    if self.makex(): axes.set_xlabel(self.makex())
    if self.makey(): axes.set_ylabel(self.makey())

    self._made = True
    axes.set_xlim(*xlimraw)
    axes.set_ylim(*ylimraw)
    return self # cascade