pythonplotenthoughtchaco

Automatic paddings in Chaco?


Is it possible to make chaco plot automatically show full output and not hiding the parts of ticks and labels? E.g. this is the output of standard example:

from chaco.api import ArrayPlotData, Plot
from enable.component_editor import ComponentEditor

from traits.api import HasTraits, Instance
from traitsui.api import View, Item


class MyPlot(HasTraits):
    plot = Instance(Plot)
    traits_view = View(Item('plot', editor = ComponentEditor(), show_label = False),
                   width = 500, height = 500, resizable = True)

def __init__(self, x, y, *args, **kw):
    super(MyPlot, self).__init__(*args, **kw)
    plotdata = ArrayPlotData(x=x,y=y)
    plot = Plot(plotdata)
    plot.plot(("x","y"), type = "line", color = "blue")
    self.plot = plot


import numpy as np
x = np.linspace(-300,300,10000)
y = np.sin(x)*x**3
lineplot = MyPlot(x,y)
lineplot.configure_traits()

enter image description here

As you see the part of tick labels are hidden.. the only thing I can do is to manually adjust left padding of the plot. But this becomes extremely incovinient when you plot different data and different scales or fonts with the plot in application. Is it possible somehow to make padding automatically adjusted to include ALL related info?

UPD.: I've found ensure_labels_bounded property for the axis, but seems it has no effect.


Solution

  • Chaco does not support advanced layout features like these. If you use Chaco, you should use it for its speed, not for nice graphs or features. That being said, here's a version as close as I could get. It requires you to re-size the window with the mouse at least once for the padding correction to take place. Maybe you can find a way to refresh the window without having to manually resize it, I didn't have any luck with that. Anyways hope that gets you on the right track.

    from chaco.api import ArrayPlotData, Plot
    from enable.component_editor import ComponentEditor
    
    from traits.api import HasTraits, Instance
    from traitsui.api import View, Item
    
    class MyPlot(HasTraits):
        plot = Instance(Plot)
        traits_view = View(Item('plot', editor = ComponentEditor(), show_label = False),
                       width = 500, height = 500, resizable = True)
    
        def __init__(self, x, y, *args, **kw):
            super(MyPlot, self).__init__(*args, **kw)
            plotdata = ArrayPlotData(x=x,y=y)
            plot = Plot(plotdata, padding=25)
            plot.plot(("x","y"), type = "line", color = "blue", name='abc')
            self.plot = plot
            # watch for changes to the bounding boxes of the tick labels
            self.plot.underlays[2].on_trait_change(self._update_size, '_tick_label_bounding_boxes')
            self.plot.underlays[3].on_trait_change(self._update_size, '_tick_label_bounding_boxes')
        def _update_size(self):
            if len(self.plot.underlays[2]._tick_label_bounding_boxes) > 0:
                self.plot.padding_bottom = int(np.amax(np.array(self.plot.underlays[2]._tick_label_bounding_boxes),0)[1]+8+4)
            if len(self.plot.underlays[3]._tick_label_bounding_boxes) > 0:
                self.plot.padding_left = int(np.amax(np.array(self.plot.underlays[3]._tick_label_bounding_boxes),0)[0]+8+4)
    
    import numpy as np
    x = np.linspace(-300,300,10000)
    y = np.sin(x)*x**3
    lineplot = MyPlot(x,y)
    lineplot.configure_traits()
    

    enter image description here