Line selection tool for kymograph velocity measurement

Hi,
The slope of a trace on a kymograph or spatio-temporal diagram gives the speed of the object that produced the trace (for more explanations also see this page on imagej.net). When I asked on the ImageJ mailing list whether measuring this slope could be made more convenient, @imagejan and Herbie Gluender sent nice macro code that provides a line-selection type tool that shows custom information in the status bar. This is a dump of @imagejan’s original suggestion along with a modified version that takes the image scale into account and writes the final values to a table.

The macros can be installed (via Plugins > Macros > Install...) into the toolbar.

Original compact tool, credits go to @imagejan:

// Author: Jan Eglinger
macro "Kymograph Line Selection Tool - L1af1Ca00V0933Ve033C00fL1afaLfaf1" {
     var leftButton = 16;
     getCursorLoc(x, y, z, flags);
     x0 = x;
     y0 = y;
     while (true) {
         getCursorLoc(x, y, z, flags);
         makeLine(x0, y0, x, y);
         showStatus("dx: " + (x-x0) + "; dy: " + (y-y0));
         if (flags&leftButton==0) {
             return;
         }
     }
}

Extended version that shows both scaled and unscaled increments, and writes the values and the slope to a table. Note that depending on how you turn your kymograph, the speed is either dx/dy or dy/dx.

// Authors: Jan Eglinger, Adrian Daerr
macro "Kymograph Line Selection Tool - L1af1Ca00V0933Ve033C00fL1afaLfaf1" {
    var leftButton = 16;
    table = "Kymograph Line Selection Slopes"
    if (! isOpen(table)) {
        Table.create(table);
        // Table possibly opens in an unconvenient location. Rather than
        // toying with setPosition, just return here and let the user
        // reposition the table before using the tool again.
        return;
    }
    getCursorLoc(x, y, z, flags);
    x0Pix = x;
    y0Pix = y;
    toScaled(x, y);
    x0 = x;
    y0 = y;
    while (true) {
        getCursorLoc(x, y, z, flags);
        makeLine(x0Pix, y0Pix, x, y);
        dxPix = x - x0Pix;
        dyPix = y - y0Pix;
        toScaled(x, y);
        dx = x - x0;
        dy = y - y0;
        s = "dx = " + dx + " (" + dxPix + "px); dy = " + dy + " (" + dyPix + "px)";
        showStatus(s);
        if (flags&leftButton == 0)
          break;
    }
    // append a row with the final values to the table
    n = Table.size(table);
    Table.set("dx(scaled)", n, dx, table);
    Table.set("dy(scaled)", n, dy, table);
    Table.set("dx(pixels)", n, dxPix, table);
    Table.set("dy(pixels)", n, dyPix, table);
    Table.set("dx/dy(scaled)", n, dx/dy, table);
    Table.set("dy/dx(scaled)", n, dy/dx, table);
    Table.set("slice", n, z, table);
    Table.set("image title", n, getTitle, table);
    Table.update(table);
    return;
}
3 Likes