Search code examples
pythonlegendchaco

Custom labels in Chaco Legend


I'd like to change the line labels on a chaco Legend because my labels need to be ascending floats:

1,2,3,4

But it is string sorting, so I'm getting:

1, 10, 11, 2, 21  etc...

I noticed the documentation seems unfinished in regard to this:

http://chaco.readthedocs.org/en/latest/user_manual/basic_elements/overlays.html#legend

I've tried setting the legends labels manually:

self.plot.legend.labels = list([i for i in self.mylist]) 

I'm using a colormap, so this is very noticeable as the legend shows blue lines and red lines mixed seemingly randomly due to the string sorting.

Below is a minimal working example

This example does not use the same colormap I'm using, but shows how the line ordering in the legend is not sorted. It's not important which colormap is used, what's important is the string sorting in the legend gives unwanted aesthetics.

from traits.api import *
from chaco.api import *
from traitsui.api import *
from chaco.example_support import COLOR_PALETTE
from enable.api import ComponentEditor
import numpy as np


class TestPlot(HasTraits):

    plot = Instance(Plot)

    traits_view = View( Item('plot', editor=ComponentEditor(), show_label=False) )

    def _plot_default(self):
        data = ArrayPlotData()
        plot = Plot(data)

        x = np.linspace(0,10,100)
        data.set_data('x', x)

        for i, freq in enumerate(range(1,20,3)):
            y = 'line_%s' % freq
            color = tuple(COLOR_PALETTE[i])
            data.set_data(y, i*x)
            plot.plot(('x', y), name=y, color=color)

        plot.legend.visible = True


        return plot


if __name__ == '__main__':
    TestPlot().configure_traits()

See screenshot:

enter image description here


Solution

  • You can add leading zeros for one digit numbers by changing the line

    y = 'line_%s' % freq 
    

    to

    y = 'line_%02d' % freq
    

    I assume you have no more than 99 graphs otherwise you need to change the 02 to 03. Then your legend should be correctly sorted.

    See https://docs.python.org/3.4/library/string.html#format-specification-mini-language for more information on the string format specifiers.

    The format 0# where # is a number, means that in the string the number uses # positions and if the number is smaller than the given width it is filled with trailing zeros. If you want floating point numbers with one digit as fractional part use %04.1f