Menu

Home

Alois
Attachments
mpl-toolbox.png (27671 bytes)

Installation

Linux

  • You can download the latest tarball from PyPI and install it using setuptools

    easy_install <tar.gz file>
    
  • Or you just download the source code via

    git clone git://git.code.sf.net/p/colorview2d/code colorview2d-code
    

    and call setup.py directly

    python setup.py install
    

Windows

Currently there is a binary available only for Win7 64bit. It can be downloaded in the [files:] section. Make sure the default plotting file ("demo.dat") and the
configuration file ("default.config") are present in the same directory.

Tools

When using the tools, you can always save the current plot as a png file using the matplotlib toolbox.

Save a png file with the matplotlib toolbox

This way you can document your work, i.e., the show linecuts or the slopes that were extracted.

Linecut mass extraction

With this tool you can extract 1d line traces (data files with two dimensions) from the 3d dataset.

Select the Linecut extraction item from the Tools menu.

First choose whether the traces are taken along the x or y axis. Along the axis means that the first column in the resulting data file will consist of the range of the respective axis. We call this axis the primary axis.

Next, you can provide a range along the primary axis. In the other direction, along the secondary axis, you can select limits and an interval to extract a series of linecuts.

The traces can be saved to a series of data files.
The filename uses curly brackets as placeholders for the running parameter on the secondary axis.

Slope extraction

Since most of the phenomena in physics are linear ;) this tool assists in extracting linear dependencies of prominent features in the dataset as a line function

y = m*x + t

by point and click.

Select Slope Extraction in the Tools Menu.

Now left click in the 2d color plot window to set the first point and right click to set the second point.

A colored line is drawn.

You can now provide a comment in the dialog and save the line to the linelist.

After you pointed out all interesting linear dependencies you can save the list to a text file for further processing.

View line traces

The tool can be used to get an impression of how a feature in the dataset evolves using line traces that can be freely selected by point and click.

Select the Linecut viewer in the Tools menu.

An additional window appears that will contain the line graphs.
Now left click at some point in the 2d color plot window and right click at another point.

A line is drawn between the two points. You can adjust the position of the two points by additional clicks.

If you are satisfied with the position of the points, click Plot on the bottom left of the tool window.
The data is plotted along the line, with the y axis representing the colorscale of the 2d plot window. The x-axis at the moment shows the number of data points traversed by the line.

The distance measure tool

Select the Measure Distance tool from the menu.

  • A distance in the direction of the x-axis can be measured by click and drag with the left mouse button.

  • A distance in the direction of the y-axis can be mesured by click and drag with the right mouse button.

As soon as you release the button, the distance is plotted next to the line. The next click replaces the line.

You can save the line and add a new one. Once you are done adding lines you can save the list to the hard drive (Save List). It is also recommended to use the matplotlib toolbox to save a png file with the distance measures.

Plugin interface

All image manipulation tools, called mods, are provided as yapsy plugins in the directory Mods/. Developing your own plugins is no rocket science. We show two examples of plugins and explain the source code.

Create your own mod and adapt colorview to your needs!

Remark: The examples are taken from the linux version of the program. Due to the packaging process, there is a slight difference in the import syntax for the plugins in the win7 version.

It is very instructive to have a look at the online documentation of the plugin interface.

The yapsy-plugin file

Every plugin has to provide a file called Modtitle.yapsy-plugin in the Mods/ folder.
This should contain at least the following information:

[Core]
Name = Modtitle
Module = Modtitle

[Documentation]
Description = Wiggle shiggle diggle the dataset
Author = The benevolent dictator
Version = 1.0

Example 1: Derive mod

The derive mod is an example for the simplemost mod possible. It uses numpy.diff to perform a numerical derivative of the dataset in the y-direction. We do not have to provide any additional parameters.

The widget for this mod consists solely of a checkbox to activate the mod. This checkbox is created already by the ModWidget base class, so that we do not have to care about widgets at all.

But let us get down to business: the file Mods/Derive.py.

import numpy as np
from colorview2d.Mods import IMod

class Derive(IMod.IMod):
    def __init__(self):
        IMod.IMod.__init__(self)
    def apply(self,datafile):
        dydata = datafile.Zdata
        dydata[:-1] = np.diff(datafile.Zdata,axis=0)
        dydata[-1] = dydata[-2]
        datafile.set_Zdata(dydata)

We have to import numpy, of course, and the Mod interface class IMod, derived from yapsy.IPlugin. This is also the class we inherit from creating our Derive mod class.

Note: There is also a online documentation of the plugin interface.

It provides the checkbox widget and adds it to the application panel. In the init function we call the init routine of the IMod plugin for this purpose. As long as you do not know exactly what you are doing you should include the call in your custom class.

In the apply routine we modify the datafile object. The datafile object represents a 3d datafile with its axes. Please have a look at the gpfile module in the colorview2d source for details. This is higly recommended if you write a plugin.

In this case we only use the function datafile.set_Zdata which should be used to replace the array.

Example 2: Median filter

The median filter plugin is a slightly more complicated example: We have to provide the size of the filter window to the plugin. To this end, we define two widgets and some additional code that handles the interaction with the plugin interface.

This is the 0.50 version of the plugin:


from colorview2d.Mods import IMod
from colorview2d.Mods.ModWidget import ModWidget

import numpy as np

from wx.lib.masked import NumCtrl,EVT_NUM

from scipy.ndimage.filters import median_filter

"""
This mod performs a median filter on the data. The window size for the
filter is specified by wx.lib.masked.NumCtrl widgets.
"""


class MedianWidget(ModWidget):
    """
    A widget to control the filter.
    Hosts two wx.lib.masked.NumCtrl widgets to specify the size of the
    filter window.
    """
    def __init__(self,mod,panel):
        ModWidget.__init__(self,mod,panel)
        self.num_median_xwidth = NumCtrl(self.panel,
                                          fractionWidth = 1,
                                          allowNegative = False)
        self.num_median_ywidth = NumCtrl(self.panel,
                                          fractionWidth = 1,
                                          allowNegative = False)

        self.Add(self.num_median_xwidth,0,self.flags,border=10)
        self.Add(self.num_median_ywidth,0,self.flags,border=10)

        self.panel.Bind(EVT_NUM,self.on_num_median,self.num_median_ywidth)
        self.panel.Bind(EVT_NUM,self.on_num_median,self.num_median_xwidth)


    def on_chk(self,event):
        if self.chk.GetValue():
            self.mod.set_args((self.num_median_xwidth.GetValue(),self.num_median_ywidth.GetValue()))
            self.mod.activate()
        else:
            self.mod.deactivate()

    def update(self):
        ModWidget.update(self)
        # Note that we call ChangeValue instead of SetValue to not trigger a
        # EVT_NUM event
        self.num_median_xwidth.ChangeValue(self.mod.args[0])
        self.num_median_ywidth.ChangeValue(self.mod.args[1])

    def on_num_median(self,event):
        if self.mod.active:
            self.mod.deactivate()
            self.mod.set_args((self.num_median_xwidth.GetValue(),self.num_median_ywidth.GetValue()))
            self.mod.activate()            



class Median(IMod.IMod):
    """
    The modification class. Applies a median filter of size

    args = (xsize, ysize)

    to the datafile.
    """
    def __init__(self):
        IMod.IMod.__init__(self)
        self.args = (0.,0.)

    def apply(self, datafile):
        datafile.set_Zdata(median_filter(datafile.Zdata,size=self.args))

    def create_widget(self,panel):
        self.panel = panel
        self.widget = MedianWidget(self,self.panel)
        return self.widget

Let us discuss this step by step.

The widget

Note that we inherit the ModWidget base class to get the basic functionality we used in the previous example.

In the init function of the widget class we first initiate the super class and then define two NumCtrl widgets from the wx.lib.masked library.

    self.num_median_xwidth = NumCtrl(self.panel,
                                      fractionWidth = 1,
                                      allowNegative = False)
    self.num_median_ywidth = NumCtrl(self.panel,
                                      fractionWidth = 1,
                                      allowNegative = False)

They can be used to enter two floats with one digit decimal precision. We add these to our plugin widget:

    self.Add(self.num_median_xwidth,0,self.flags,border=10)
    self.Add(self.num_median_ywidth,0,self.flags,border=10)

The parameters are explained in the [docs] (http://www.wxpython.org/docs/api/wx.Sizer-class.html#Add). We then bind the event triggered by this control (EVT_NUM) to the routine on_num_median.

We have to overwrite on_chk in this widget since we want to update the parameters in the mod once someone clicks the checkbox:

def on_chk(self,event):
    if self.chk.GetValue():
        self.mod.set_args((self.num_median_xwidth.GetValue(),self.num_median_ywidth.GetValue()))
        self.mod.activate()
    else:
        self.mod.deactivate()

Be careful to use the interface functions set_args, activate and deactivate for this purpose.

The update routine has to be overwritten to provide the reverse functionality: If a config file is loaded that contains a set of parameters for this plugin, it has to be updated correctly. This is done here:

def update(self):
    ModWidget.update(self)
    # Note that we call ChangeValue instead of SetValue to not trigger a
    # EVT_NUM event
    self.num_median_xwidth.ChangeValue(self.mod.args[0])
    self.num_median_ywidth.ChangeValue(self.mod.args[1])

Note that we call the update function of our ancestor to update the checkbox. Then ChangeValue is used to set the mod arguments in the widget.

Finally, we specify the function that is bound to the EVT_NUM event:

def on_num_median(self,event):
    if self.mod.active:
        self.mod.deactivate()
        self.mod.set_args((self.num_median_xwidth.GetValue(),self.num_median_ywidth.GetValue()))
        self.mod.activate()

If the mod is active we first deactivate it, then set the new values and activate it again. At the moment there is no functionality to update the plugin in place within the mod pipeline.

The mod

The actual plugin is rather slim. We initate the super class and specify default arguments in the init routine.

All the work is done by the one-liner

    datafile.set_Zdata(median_filter(datafile.Zdata,size=self.args))

in the apply function, thanks to scipy.ndimage.filters. In the last member function of the Median class we create the MedianWidget. Make sure to provide a parameter panel as a reference to the panel of the main window.
The function should return the widget.

So that's it. With this example you are good to go for your own cv2d plugin.