Last active
December 19, 2015 14:08
-
-
Save jmmateoshggm/5966574 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.awt.Color; | |
import java.awt.Font; | |
import java.awt.event.ActionEvent; | |
import java.awt.event.ActionListener; | |
import java.awt.event.KeyEvent; | |
import java.awt.event.KeyListener; | |
import java.awt.event.MouseEvent; | |
import java.awt.event.MouseListener; | |
import java.awt.event.MouseMotionListener; | |
import java.awt.event.WindowEvent; | |
import java.awt.event.WindowListener; | |
import javax.swing.JCheckBox; | |
import javax.swing.JFrame; | |
import javax.swing.JLabel; | |
import javax.swing.JPanel; | |
import javax.swing.border.EmptyBorder; | |
import ij.IJ; | |
import ij.ImagePlus; | |
import ij.ImageStack; | |
import ij.gui.ImageCanvas; | |
import ij.gui.Plot; | |
import ij.gui.PlotWindow; | |
import ij.measure.Calibration; | |
import ij.plugin.filter.PlugInFilter; | |
import ij.process.ImageProcessor; | |
/** | |
* <p> | |
* Dynamic Pixel Inspector ImageJ plugin. | |
* </p> | |
* | |
* <p> | |
* This plugin allows the user to watch the intensity curve of each | |
* pixel through the different frames by just moving the mouse pointer over | |
* the image or, in the "Disabled" mode, by clicking over the image. | |
* The plugin works properly with 4D (3D + time) or 3D (2D + time) images but | |
* the user must be careful to open the image in a way that the time | |
* information has been correctly placed (HyperStacks). | |
* </p> | |
* | |
* @author First version by | |
* <a href="mailto:pedro.macias.gordaliza@gmail.com">Pedro Macías | |
* Gordaliza</a>, with later improvements by | |
* <a href="mailto:jmmateos@hggm.es">José María Mateos</a>. | |
* @version 1.1 | |
* | |
*/ | |
public class Dynamic_Pixel_Inspector implements PlugInFilter, ActionListener, | |
WindowListener, MouseListener, MouseMotionListener, | |
KeyListener { | |
private ImagePlus imp; | |
private ImageCanvas canvas; | |
private ImageStack is; | |
private Calibration cal; | |
private PlotWindow pw; | |
private JFrame jf; | |
private JLabel enabled; | |
private int dim[]; | |
private boolean moveFlag = true; | |
private boolean invert = false; | |
// run method from PlugInFilter | |
public void run(ImageProcessor arg0) { | |
enabled = new JLabel(); | |
enabled.setBounds(10, 11, 89, 23); | |
changeEnabledLabel(); | |
jf = createFrame(); | |
jf.addWindowListener(this); | |
jf.setVisible(true); | |
turnOn(); | |
} | |
// setup method from PlugInFilter | |
public int setup(String arg0, ImagePlus imp) { | |
int dim[] = imp.getDimensions(); | |
if(dim[4] <= 1) { | |
IJ.error("This plugin only works on HyperStacks."); | |
return DONE; | |
} else { | |
this.imp = imp; | |
this.dim = dim; | |
cal = imp.getCalibration(); | |
is = imp.getStack(); | |
canvas = imp.getCanvas(); | |
return DOES_ALL; | |
} | |
} | |
/** | |
* Changes the value of the {@code invert} parameter when the appropriate | |
* GUI element is modified. | |
*/ | |
@Override | |
public void actionPerformed(ActionEvent e) { | |
String type = e.getSource().getClass().getName(); | |
if (type.equals("javax.swing.JCheckBox")) { | |
JCheckBox jcb = (JCheckBox)e.getSource(); | |
invert = jcb.isSelected(); | |
} | |
} | |
/** | |
* Modifies the value of the {@code enabled} label. | |
*/ | |
private void changeEnabledLabel() { | |
if (moveFlag) { | |
enabled.setText("Enabled"); | |
enabled.setForeground(Color.green); | |
} else { | |
enabled.setText("Disabled"); | |
enabled.setForeground(Color.red); | |
} | |
} | |
/** | |
* Creates the main JFrame used in this plugin. | |
*/ | |
private JFrame createFrame() { | |
JFrame frame = new JFrame(); | |
frame.setTitle("Dynamic Pixel Inspector"); | |
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); | |
frame.setBounds(100, 100, 288, 94); | |
JPanel contentPane = new JPanel(); | |
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); | |
frame.setContentPane(contentPane); | |
contentPane.setLayout(null); | |
contentPane.add(enabled); | |
JCheckBox chckboxInvertValues = new JCheckBox("Invert values"); | |
chckboxInvertValues.setBounds(139, 11, 97, 23); | |
chckboxInvertValues.addActionListener(this); | |
contentPane.add(chckboxInvertValues); | |
JLabel lblPressCtrl = new JLabel("Press 'q' for enabling or disabling" + | |
" continous plotting"); | |
lblPressCtrl.setFont(new Font("Tahoma", Font.PLAIN, 8)); | |
lblPressCtrl.setBounds(20, 42, 216, 14); | |
contentPane.add(lblPressCtrl); | |
return frame; | |
} | |
@Override | |
public void windowClosed(WindowEvent e) { | |
turnOff(); | |
} | |
@Override | |
public void keyPressed(KeyEvent arg0) { | |
// Catch the event that enables or disables plot updating | |
if (arg0.getKeyCode() == KeyEvent.VK_Q) { | |
moveFlag = !moveFlag; | |
changeEnabledLabel(); | |
} | |
} | |
@Override | |
public void mouseMoved(MouseEvent arg0) { | |
if (moveFlag) | |
mouseClicked(arg0); | |
} | |
/** | |
* Does the actual plotting. | |
*/ | |
@Override | |
public void mouseClicked(MouseEvent e) { | |
int offscreenX = canvas.offScreenX(e.getX()); | |
int offscreenY = canvas.offScreenY(e.getY()); | |
double[] y = getTAC(offscreenX, offscreenY, imp.getSlice()); | |
if (y != null) { | |
// Fill in X axis (frame number) | |
double[] x = new double[dim[4]]; | |
for (int i = 1; i <= x.length; i++) | |
x[i - 1] = i; | |
// Fill in Y axis (image intensity) | |
if (invert) | |
for (int i = 0; i < y.length; i++) | |
y[i] = -y[i]; | |
// Prepare plot window | |
Plot chart = new Plot("Slice = " + imp.getSlice() + ", x = " | |
+ offscreenX + ", y = " + offscreenY, | |
"Frame number", "Intensity (calibrated)", x, y); | |
if (pw == null) { | |
pw = chart.show(); | |
pw.addWindowListener(this); | |
} else | |
pw.setTitle("Slice = " + imp.getSlice() + ", x = " + offscreenX | |
+ ", y = " + offscreenY); | |
// Add the points for prettier plots | |
chart.addPoints(x, y, PlotWindow.CIRCLE); | |
pw.drawPlot(chart); | |
} | |
} | |
/** | |
* Enable the events | |
*/ | |
private void turnOn() { | |
canvas.addMouseListener(this); | |
canvas.addMouseMotionListener(this); | |
canvas.addKeyListener(this); | |
} | |
/** | |
* Disable the events | |
*/ | |
private void turnOff() { | |
canvas.removeMouseMotionListener(this); | |
canvas.removeMouseListener(this); | |
canvas.removeKeyListener(this); | |
} | |
/** | |
* Returns the TAC (time-activity curve) for the given x, y and slice | |
* coordinates. | |
*/ | |
private double[] getTAC(int x, int y, int slice) { | |
// Dimension check | |
if (x >= dim[0] || x < 0 || y >= dim[1] || y < 0 || slice > dim[3] | |
|| slice < 1) { | |
return null; | |
} | |
// Alloc space for the result | |
double[] result = new double[dim[4]]; | |
// Set the desired slice and iterate through the frames | |
for (int frame = 1; frame <= dim[4]; frame++) { | |
int stack_number = imp.getStackIndex(dim[2], slice, frame); | |
// Use calibration to return true value | |
result[frame - 1] = cal.getCValue( | |
is.getVoxel(x, y, stack_number - 1)); | |
} | |
return result; | |
} | |
/* | |
* UNUSED METHODS | |
*/ | |
@Override | |
public void windowOpened(WindowEvent e) {} | |
@Override | |
public void windowClosing(WindowEvent e) {} | |
@Override | |
public void windowIconified(WindowEvent e) {} | |
@Override | |
public void windowDeiconified(WindowEvent e) {} | |
@Override | |
public void windowActivated(WindowEvent e) {} | |
@Override | |
public void windowDeactivated(WindowEvent e) {} | |
@Override | |
public void keyReleased(KeyEvent arg0) {} | |
@Override | |
public void keyTyped(KeyEvent arg0) {} | |
@Override | |
public void mouseDragged(MouseEvent arg0) {} | |
@Override | |
public void mouseEntered(MouseEvent e) {} | |
@Override | |
public void mouseExited(MouseEvent e) {} | |
@Override | |
public void mousePressed(MouseEvent e) {} | |
@Override | |
public void mouseReleased(MouseEvent e) {} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment