如何使用Chaco覆盖两个图像?

时间:2015-06-05 10:41:07

标签: python plot overlay chaco

注意:我将自己回答这个问题,以帮助将来遇到此问题的其他人。如果您愿意,请随时提交您自己的答案,但要知道它已经回答了!

如何将带有一个色彩映射的蒙面图像叠加到Chaco中具有不同色彩映射的另一个图像上?另外,我如何为每个颜色添加颜色栏?

2 个答案:

答案 0 :(得分:1)

在Chaco中以这种方式叠加图像并没有很好的记录,但绝对可能。首先,你如何用chaco绘制蒙面图像?使用Plot().img_plot()绘图时,Chaco使用np.nan值作为透明像素。例如,绘图:

img = np.eye(100)
img[img==0] = np.nan

会绘制一条透明背景的对角线。

但是你如何将这个图像叠加在另一个图像上呢?

有两种主要方法可以做到这一点。

  1. 制作两个单独的图并使用OverlayPlotContainer
  2. 堆叠它们
  3. 制作一个图并在一个图中绘制它们
  4. 第二种方法的优点是两个图像都使用相同的轴。此外,如果您在与第一个图像相同的图中绘制第二个图像,它将保持相同的像素长宽比。这意味着如果您绘制100x100图像,然后在其上方覆盖50x50图像,则覆盖图像将仅占用从(0,0)开始的整个图形的25%。

    第二种方法存在一些问题,因此我将解释如何纠正它们。

    当您在同一个Plot对象上绘制多个图像时(使用img_plot()),默认情况下它们都将使用相同的color_mapper。这意味着两者都将缩放到相同的范围。这可能不是必需的结果,因此您必须为两个图像创建新的color_mappers。

    这是一些使用TraitsUI的示例代码,它是根据Qt代码改编的。

    from traits.api import HasTraits, Instance
    from traitsui.api import Item, View
    from enable.api import ComponentEditor
    from chaco.api import ArrayPlotData, Plot, ColorBar, LinearMapper, HPlotContainer, DataRange1D, ImageData
    import chaco.default_colormaps
    #
    import numpy as np
    
    class ImagePlot(HasTraits):
        plot = Instance(HPlotContainer)
    
        traits_view = View(
            Item('plot', editor=ComponentEditor(), show_label=False), width=500, height=500, resizable=True, title="Chaco Plot")
    
        def _plot_default(self):
            bottomImage = np.reshape(np.repeat(np.linspace(0, 5, 100),100), (100,100))
            topImage = np.eye(50)
            topImage = topImage*np.reshape(np.repeat(np.linspace(-2, 2, 50),50), (50,50))
            topImage[topImage==0] = np.nan
            #
            bottomImageData = ImageData()
            bottomImageData.set_data(bottomImage)
            #
            topImageData = ImageData()
            topImageData.set_data(topImage)
            #
            plotData = ArrayPlotData(imgData=bottomImageData, imgData2=topImageData)
            plot = Plot(plotData, name='My Plot')
            plot.img_plot("imgData")
            plot.img_plot("imgData2")
            # Note: DO NOT specify a colormap in the img_plot!
            plot.aspect_ratio = 1.0
            #
            bottomRange = DataRange1D()
            bottomRange.sources = [plotData.get_data("imgData")]
            topRange = DataRange1D()
            topRange.sources = [plotData.get_data("imgData2")]
            plot.plots['plot0'][0].color_mapper = chaco.default_colormaps.gray(bottomRange)
            plot.plots['plot1'][0].color_mapper = chaco.default_colormaps.jet(topRange)
            #
            colormapperBottom = plot.plots['plot0'][0].color_mapper
            colormapperTop = plot.plots['plot1'][0].color_mapper
            #
            colorbarBottom = ColorBar(index_mapper=LinearMapper(range=colormapperBottom.range), color_mapper=colormapperBottom, orientation='v', resizable='v', width=30, padding=20)
            colorbarBottom.padding_top = plot.padding_top
            colorbarBottom.padding_bottom = plot.padding_bottom
            #
            colorbarTop = ColorBar(index_mapper=LinearMapper(range=colormapperTop.range), color_mapper=colormapperTop, orientation='v', resizable='v', width=30, padding=20)
            colorbarTop.padding_top = plot.padding_top
            colorbarTop.padding_bottom = plot.padding_bottom
            #
            container = HPlotContainer(resizable = "hv", bgcolor='transparent', fill_padding=True, padding=0)
            container.spacing = 0
            container.add(plot)
            container.add(colorbarBottom)
            container.add(colorbarTop)
            #
            return container
    
    if __name__ == "__main__":
        ImagePlot().configure_traits()
    

    Overlaying image plots in Chaco

答案 1 :(得分:1)

我没有100%归功于此,通过在线快速搜索,我发现您可以使用以下代码进行简单的叠加:

找到的来源:

http://docs.enthought.com/chaco/user_manual/containers.html#overlayplotcontainer

参考代码:

class OverlayImageExample(HasTraits):

plot = Instance(OverlayImage)

traits_view = View(
    Item('plot', editor=ComponentEditor(), show_label=False),
    width=800, height=600, resizable=True
)

def _plot_default(self):
    # Create data
    x = linspace(-5, 15.0, 100)
    y = jn(3, x)
    pd = ArrayPlotData(index=x, value=y)

    zoomable_plot = Plot(pd)
    zoomable_plot.plot(('index', 'value'),
                       name='external', color='red', line_width=3)

    # Attach tools to the plot
    zoom = ZoomTool(component=zoomable_plot,
                    tool_mode="box", always_on=False)
    zoomable_plot.overlays.append(zoom)
    zoomable_plot.tools.append(PanTool(zoomable_plot))

    # Create a second inset plot, not resizable, not zoom-able
    inset_plot = Plot(pd)
    inset_plot.plot(('index', 'value'), color='blue')
    inset_plot.set(resizable = '',
                   bounds = [250, 150],
                   position = [450, 350],
                   border_visible = True
                   )

    # Create a container and add our plots
    container = OverlayPlotContainer()
    container.add(zoomable_plot)
    container.add(inset_plot)
    return container