Minor tick labels not drawn when placed on top

Hi, Florent! :wink:

[...]

This causes minor tick labels not to be drawn when using tick_top(), as
shown in the attached example (+ two lines patch).

This part of my mail still applies, AFAICT.

Note: I stumbled accross this because I draw a few vlines on a plot to
      mark specific values and I wanted a label indicating what each
      vline means. I managed to add these labels with minor ticks using
      a FixedLocator and a FixedFormatter, but the minor tick labels
      where colliding with the major ones. Therefore, I tried to move
      them to the top.

For this one, however, I have found a better solution. FixedLocator and
FixedFormatter are easy to use, but:

   1. They replace one of your two major/minor ticks&ticklabels sets.
   2. They don't allow you (AFAIK) do draw the labels on the other side
      of the axis line (i.e., above the axis line when using
      tick_bottom(), below the axis line when using tick_top()), which
      caused ugly overlaps with major tick labels in my case.

The better solution simply consists in mimicking what is done in axis.py
to place tick labels. A small loop over the positions and label strings,
mixed with a transformation, and voil�! The labels are placed just as
they should, offset a bit to the left (to avoid clashing with the vline
they correspond to) and top from the position on the x axis, with the
offsets given in dpi, and therefore correct whatever resolution is
chosen to render the figure.

Special congrats for having included this dpi setting as lazy value in
the core design, despite the usual habit of working directly in pixels.

For the curious, here is the relevant part of code:

    pos = [ self.mean, self.d1, self.q1, self.median, self.q3, self.d9 ]
    labels = [ u"mo", u"d1", u"q1", u"md", u"q3", u"d9" ]
    colors = [ 'r', '#6b8e23', '#cc5522', 'b', 'c', 'm']

    # We are going to draw a vertical line at each position with a label
    # nearby.

···

Florent Rougon <f.rougon@...207...> wrote:
    #
    # Bad method for the label placement: using minor ticks. The biggest
    # problem is that it doesn't allow drawing the labels above the x axis
    # line; consequently, they often collide with the major tick labels,
    # which looks quite ugly:
    #
    # self.axes.xaxis.set_minor_locator(FixedLocator(pos))
    # self.axes.xaxis.set_minor_formatter(FixedFormatter(labels))
    #
    # Good method: place the labels by hand, just the way it is done in
    # matplotlib/axis.py for tick labels. For this, we use a transform
    # that will be passed to self.axes.text() and will translate each
    # label by the following offset, in PostScript points (1/72 inch):
    xoffset, yoffset = -3., 2.
    # The same offset in pixels, based on the figure's dpi value
    xo_pixels = Value(xoffset)*self.axes.figure.dpi*Value(1/72.)
    yo_pixels = Value(yoffset)*self.axes.figure.dpi*Value(1/72.)

    # We are going to transform x data coordinates and y Axes coordinates
    # into backend coordinates (pixels).
    trans = blend_xy_sep_transform(self.axes.transData,
                                   self.axes.transAxes)

    # The label text will be offset with a post-transformation
    transOffset = translation_transform(xo_pixels, yo_pixels)
    trans.set_offset((0,0), transOffset)

    for i in xrange(len(pos)):
        # Draw the line
        self.axes.axvline(x=pos[i], ymin=0., ymax=1., color=colors[i])
        # Place the corresponding label; x is in data coordinates and y in
        # Axes coordinates.
        self.axes.text(x=pos[i], y=0., s=labels[i],
                       fontsize=rcParams["tick.labelsize"],
                       verticalalignment='bottom',
                       horizontalalignment='right', transform=trans)

--
Florent