package ij.plugin;
import ij.*;
import ij.gui.*;
import ij.process.*;
import ij.measure.*;
import ij.plugin.filter.Analyzer;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import java.util.*;
/** This plugin generates gel profile plots that can be analyzed using
the wand tool. It is similar to the "Gel Plotting Macros" in NIH Image. */
public class GelAnalyzer implements PlugIn {
static final String OPTIONS = "gel.options";
static final String VSCALE = "gel.vscale";
static final String HSCALE = "gel.hscale";
static final int OD=1, PERCENT=2, OUTLINE=4, INVERT=8;
static int saveID;
static int nLanes, saveNLanes;
static Rectangle firstRect;
static final int MAX_LANES = 100;
static int[] x = new int[MAX_LANES+1];
static PlotsCanvas plotsCanvas;
static ImageProcessor ipLanes;
static ImagePlus gel;
static int plotHeight;
static int options = (int)Prefs.get(OPTIONS, PERCENT+INVERT);
static boolean uncalibratedOD = (options&OD)!=0;
static boolean labelWithPercentages = (options&PERCENT)!=0;;
static boolean outlineLanes;
static boolean invertPeaks = (options&INVERT)!=0;
static double verticalScaleFactor = Prefs.get(VSCALE, 1.0);
static double horizontalScaleFactor = Prefs.get(HSCALE, 1.0);
static Overlay overlay;
boolean invertedLut;
ImagePlus imp;
Font f;
double odMin=Double.MAX_VALUE, odMax=-Double.MAX_VALUE;
static boolean isVertical;
static boolean showLaneDialog = true;
public void run(String arg) {
if (arg.equals("options")) {
showDialog();
return;
}
imp = WindowManager.getCurrentImage();
if (imp==null) {
IJ.noImage();
return;
}
if (arg.equals("reset")) {
nLanes = 0;
saveNLanes = 0;
saveID = 0;
if (plotsCanvas!=null)
plotsCanvas.reset();
ipLanes = null;
overlay = null;
if (gel!=null) {
ImageCanvas ic = gel.getCanvas();
if (ic!=null) ic.setDisplayList(null);
gel.draw();
}
return;
}
if (arg.equals("percent") && plotsCanvas!=null) {
plotsCanvas.displayPercentages();
return;
}
if (arg.equals("label") && plotsCanvas!=null) {
if (plotsCanvas.counter==0)
show("There are no peak area measurements.");
else
plotsCanvas.labelPeaks();
return;
}
if (imp.getID()!=saveID) {
nLanes=0;
ipLanes = null;
saveID = 0;
}
if (arg.equals("replot")) {
if (saveNLanes==0) {
show("The data needed to re-plot the lanes is not available");
return;
}
nLanes = saveNLanes;
plotLanes(gel, true);
return;
}
if (arg.equals("draw")) {
outlineLanes();
return;
}
Roi roi = imp.getRoi();
if (roi==null || roi.getType()!=Roi.RECTANGLE) {
show("Rectangular selection required.");
return;
}
Rectangle rect = roi.getBounds();
if (nLanes==0) {
invertedLut = imp.isInvertedLut();
IJ.register(GelAnalyzer.class); // keeps this class from being GC'd
}
if (arg.equals("first")) {
selectFirstLane(rect);
return;
}
if (nLanes==0) {
show("You must first use the \"Select First Lane\" command.");
return;
}
if (arg.equals("next")) {
selectNextLane(rect);
return;
}
if (arg.equals("plot")) {
if (( isVertical && (rect.x!=x[nLanes]) ) || ( !(isVertical) && (rect.y!=x[nLanes]) )) {
selectNextLane(rect);
}
plotLanes(gel, false);
return;
}
}
void showDialog() {
GenericDialog gd = new GenericDialog("Gel Analyzer");
gd.addNumericField("Vertical scale factor:", verticalScaleFactor, 1);
gd.addNumericField("Horizontal scale factor:", horizontalScaleFactor, 1);
gd.addCheckbox("Uncalibrated OD", uncalibratedOD);
gd.addCheckbox("Label with percentages", labelWithPercentages);
gd.addCheckbox("Invert peaks", invertPeaks);
gd.addHelp(IJ.URL+"/docs/menus/analyze.html#gels");
gd.showDialog();
if (gd.wasCanceled())
return;
verticalScaleFactor = gd.getNextNumber();
horizontalScaleFactor = gd.getNextNumber();
uncalibratedOD = gd.getNextBoolean();
labelWithPercentages = gd.getNextBoolean();
invertPeaks = gd.getNextBoolean();
options = 0;
if (uncalibratedOD) options |= OD;
if (labelWithPercentages) options |= PERCENT;
if (invertPeaks) options |= INVERT;
if (verticalScaleFactor==0.0) verticalScaleFactor=1.0;
if (horizontalScaleFactor==0.0) horizontalScaleFactor=1.0;
Prefs.set(OPTIONS, options);
Prefs.set(VSCALE, verticalScaleFactor);
Prefs.set(HSCALE, horizontalScaleFactor);
}
void selectFirstLane(Rectangle rect) {
if (rect.width/rect.height>=2 || IJ.altKeyDown()) {
if (showLaneDialog) {
String msg = "Are the lanes really horizontal?\n \n"+
"ImageJ assumes the lanes are\n"+
"horizontal if the selection is more\n"+
"than twice as wide as it is tall. Note\n"+
"that the selection can only be moved\n"+
"vertically when the lanes are horizontal.";
GenericDialog gd = new GenericDialog("Gel Analyzer");
gd.addMessage(msg);
gd.setOKLabel("Yes");
gd.showDialog();
if (gd.wasCanceled()) return;
showLaneDialog = false;
}
isVertical = false;
} else
isVertical = true;
/*
if ( (isVertical && (rect.height/rect.width)<2 ) || (!isVertical && (rect.width/rect.height)<2 ) ) {
GenericDialog gd = new GenericDialog("Lane Orientation");
String[] orientations = {"Vertical","Horizontal"};
int defaultOrientation = isVertical?0:1;
gd.addChoice("Lane Orientation:", orientations, orientations[defaultOrientation]);
gd.showDialog();
if (gd.wasCanceled())
return;
String orientation = gd.getNextChoice();
if(orientation.equals(orientations[0]))
isVertical=true;
else
isVertical=false;
}
*/
IJ.showStatus("Lane 1 selected ("+(isVertical?"vertical":"horizontal")+" lanes)");
firstRect = rect;
nLanes = 1;
saveNLanes = 0;
if(isVertical)
x[1] = rect.x;
else
x[1] = rect.y;
gel = imp;
saveID = imp.getID();
overlay = null;
updateRoiList(rect);
}
void selectNextLane(Rectangle rect) {
if (rect.width!=firstRect.width || rect.height!=firstRect.height) {
show("Selections must all be the same size.");
return;
}
if (nLanesmax)
max = pp.getMax();
if (uncalibratedOD)
profiles[i] = od(profiles[i]);
}
if (uncalibratedOD) {
min = odMin;
max = odMax;
}
if (isVertical)
plotWidth = firstRect.height;
else
plotWidth = firstRect.width;
if (plotWidth<650)
plotWidth = 650;
if (isVertical) {
if (plotWidth>4*firstRect.height)
plotWidth = 4*firstRect.height;
} else {
if (plotWidth>4*firstRect.width)
plotWidth = 4*firstRect.width;
}
if (verticalScaleFactor==0.0) verticalScaleFactor=1.0;
if (horizontalScaleFactor==0.0) horizontalScaleFactor=1.0;
Dimension screen = IJ.getScreenSize();
if (plotWidth>screen.width-screen.width/6)
plotWidth = screen.width - screen.width/6;
plotWidth = (int)(plotWidth*horizontalScaleFactor);
plotHeight = plotWidth/2;
if (plotHeight<250) plotHeight = 250;
// if (plotHeight>500) plotHeight = 500;
plotHeight = (int)(plotHeight*verticalScaleFactor);
ImageProcessor ip = new ByteProcessor(plotWidth, topMargin+nLanes*plotHeight+bottomMargin);
ip.setColor(Color.white);
ip.fill();
ip.setColor(Color.black);
//draw border
int h= ip.getHeight();
ip.moveTo(0,0);
ip.lineTo(plotWidth-1,0);
ip.lineTo(plotWidth-1, h-1);
ip.lineTo(0, h-1);
ip.lineTo(0, 0);
ip.moveTo(0, h-2);
ip.lineTo(plotWidth-1, h-2);
String s = imp.getTitle()+"; ";
Calibration cal = imp.getCalibration();
if (cal.calibrated())
s += cal.getValueUnit();
else if (uncalibratedOD)
s += "Uncalibrated OD";
else
s += "Uncalibrated";
ip.moveTo(5,topMargin);
ip.drawString(s);
double xScale = (double)plotWidth/profiles[1].length;
double yScale;
if ((max-min)==0.0)
yScale = 1.0;
else
yScale = plotHeight/(max-min);
for (int i=1; i<=nLanes; i++) {
double[] profile = profiles[i];
int top = (i-1)*plotHeight + topMargin;
int base = top+plotHeight;
ip.moveTo(0, base);
ip.lineTo((int)(profile.length*xScale), base);
ip.moveTo(0, base-(int)((profile[0]-min)*yScale));
for (int j = 1; jodMax) odMax = v;
profile[i] = v;
}
return profile;
}
void outlineLanes() {
if (gel==null || overlay==null) {
show("Data needed to outline lanes is no longer available.");
return;
}
int lineWidth = (int)(1.0/gel.getCanvas().getMagnification());
if (lineWidth<1)
lineWidth = 1;
Font f = new Font("Helvetica", Font.PLAIN, 12*lineWidth);
ImageProcessor ip = gel.getProcessor();
ImageProcessor ipLanes = ip.duplicate();
if (!(ipLanes instanceof ByteProcessor))
ipLanes = ipLanes.convertToByte(true);
ipLanes.setFont(f);
ipLanes.setLineWidth(lineWidth);
setCustomLut(ipLanes);
ImagePlus lanes = new ImagePlus("Lanes of "+gel.getShortTitle(), ipLanes);
lanes.changes = true;
lanes.setRoi(gel.getRoi());
gel.deleteRoi();
for (int i=0; iscreen.width)
w = screen.width-loc.x-20;
if (loc.y+h>screen.height)
h = screen.height-loc.y-30;
win.setSize(w, h);
win.validate();
repaintWindow();
}
}
class PlotsCanvas extends ImageCanvas {
public static final int MAX_PEAKS = 200;
double[] actual = {428566.00,351368.00,233977.00,99413.00,60057.00,31382.00,
14531.00,7843.00,2146.00,752.00,367.00};
double[] measured = new double[MAX_PEAKS];
Rectangle[] rect = new Rectangle[MAX_PEAKS];
int counter;
ResultsTable rt;
public PlotsCanvas(ImagePlus imp) {
super(imp);
}
public void mousePressed(MouseEvent e) {
super.mousePressed(e);
Roi roi = imp.getRoi();
if (roi==null)
return;
if (roi.getType()==Roi.LINE)
Roi.setColor(Color.blue);
else
Roi.setColor(Color.yellow);
if (Toolbar.getToolId()!=Toolbar.WAND || IJ.spaceBarDown())
return;
if (IJ.shiftKeyDown()) {
IJ.showMessage("Gel Analyzer", "Unable to measure area because shift key is down.");
imp.deleteRoi();
counter = 0;
return;
}
ImageStatistics stats = imp.getStatistics();
if (counter==0) {
rt = ResultsTable.getResultsTable();
rt.reset();
}
//IJ.setColumnHeadings(" \tArea");
double perimeter = roi.getLength();
String error = "";
double circularity = 4.0*Math.PI*(stats.pixelCount/(perimeter*perimeter));
if (circularity<0.025)
error = " (error?)";
double area = stats.pixelCount+perimeter/2.0; // add perimeter/2 to account area under border
Calibration cal = imp.getCalibration();
area = area*cal.pixelWidth*cal.pixelHeight;
rect[counter] = roi.getBounds();
//area += (rect[counter].width/rect[counter].height)*1.5;
// adjustment for small peaks from NIH Image gel macros
int places = cal.scaled()?3:0;
rt.incrementCounter();
rt.addValue("Area", area);
rt.show("Results");
measured[counter] = area;
if (counter500;
if (r.height>=(GelAnalyzer.plotHeight-11))
fits = true;
if (!fits)
y = r.y - 2;
ip.drawString(s, x, y);
}
imp.updateAndDraw();
displayPercentages();
//Toolbar.getInstance().setTool(Toolbar.RECTANGLE);
reset();
}
void displayPercentages() {
ResultsTable rt = ResultsTable.getResultsTable();
rt.reset();
//IJ.setColumnHeadings(" \tarea\tpercent");
double total = 0.0;
for (int i=0; i
Ads help maintain this website.