2 added + 5 modified, total 7 files
java/trunk/monitoring-app/src/main/java/org/hps/monitoring/ecal
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/ecal/Cluster.java (rev 0)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/ecal/Cluster.java 2014-02-25 16:44:47 UTC (rev 255)
@@ -0,0 +1,136 @@
+package org.hps.monitoring.ecal;
+
+import java.awt.Point;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The class <code>Cluster</code> represents a seed hit and a collection
+ * of additional hits that together form a hit cluster.
+ *
+ * @author Kyle McCarty
+ */
+public class Cluster {
+ private final Point seed;
+ private ArrayList<Point> hitList = new ArrayList<Point>();
+ private ArrayList<Point> shareList = new ArrayList<Point>();
+
+ /**
+ * <b>Cluster</b><br/><br/>
+ * <code>public <b>Cluster</b>(int ix, int iy)</code><br/><br/>
+ * Creates a new cluster. All clusters are required to have a seed
+ * hit.
+ * @param ix - The seed hit's x-coordinate.
+ * @param iy - The seed hit's y-coordinate.
+ */
+ public Cluster(int ix, int iy) { this(new Point(ix, iy)); }
+
+ /**
+ * <b>Cluster</b><br/><br/>
+ * <code>public <b>Cluster</b>(EcalHit seed)</code><br/><br/>
+ * Creates a new cluster. All clusters are required to have a seed
+ * hit.
+ * @param seed - The <code>Point</code> object indicating in which
+ * crystal the seed hit occurred.
+ */
+ public Cluster(Point seed) { this.seed = seed; }
+
+ /**
+ * <b>addComponentHit</b><br/><br/>
+ * <code>public void <b>addComponentHit</b>(int ix, int iy)</code><br/><br/>
+ * Adds an <code>Point</code> to the list of this cluster's
+ * component hits.
+ * @param ix - The component hit's x-coordinate.
+ * @param iy - The component hit's y-coordinate.
+ */
+ public void addComponentHit(int ix, int iy) { hitList.add(new Point(ix, iy)); }
+
+ /**
+ * <b>addComponentHit</b><br/><br/>
+ * <code>public void <b>addComponentHit</b>(Point eHit)</code><br/><br/>
+ * Adds an <code>Point</code> to the list of this cluster's
+ * component hits.
+ * @param eHit - The <code>Point</code> object indicating in which
+ * crystal the hit occurred.
+ */
+ public void addComponentHit(Point eHit) { hitList.add(eHit); }
+
+ /**
+ * <b>addSharedHit</b><br/><br/>
+ * <code>public void <b>addSharedHit</b>(int ix, int iy)</code><br/><br/>
+ * Adds an <code>Point</code> to the list of this cluster's shared
+ * hits.
+ * @param ix - The shared hit's x-coordinate.
+ * @param iy - The shared hit's y-coordinate.
+ */
+ public void addSharedHit(int ix, int iy) { shareList.add(new Point(ix, iy)); }
+
+ /**
+ * <b>addSharedHit</b><br/><br/>
+ * <code>public void <b>addSharedHit</b>(Point eHit)</code><br/><br/>
+ * Adds an <code>Point</code> to the list of this cluster's shared
+ * hits.
+ * @param eHit - The <code>Point</code> object indicating in which
+ * crystal the hit occurred.
+ */
+ public void addSharedHit(Point eHit) { shareList.add(eHit); }
+
+ /**
+ * <b>getComponentHits</b><br/><br/>
+ * <code>public List<Point> <b>getComponentHits</b>()</code><br/><br/>
+ * Gets the list of hits that make up the cluster, exempting the
+ * seed hit and shared hits.
+ * @return Returns the cluster hits as a <code>List</code> object
+ * composed of <code>Point</code> objects.
+ */
+ public List<Point> getComponentHits() { return hitList; }
+
+ /**
+ * <b>getSharedHits</b><br/><br/>
+ * <code>public List<Point> <b>getSharedHits</b>()</code><br/><br/>
+ * Gets the list of hits that make up the cluster, exempting the
+ * seed hit and component hits.
+ * @return Returns the shared hits as a <code>List</code> object
+ * composed of <code>Point</code> objects.
+ */
+ public List<Point> getSharedHits() { return shareList; }
+
+ /**
+ * <b>getSeedHit</b><br/><br/>
+ * <code>public EcalHit <b>getSeedHit</b>()</code><br/><br/>
+ * Gets the hit representing the cluster center.
+ * @return Returns the cluster center hit as an <code>EcalHit
+ * </code>.
+ */
+ public Point getSeedHit() { return seed; }
+
+ /**
+ * <b>getHitCount</b><br/><br/>
+ * <code>public int <b>getHitCount</b>()</code><br/><br/>
+ * Indicates how many total hits compose this cluster. This includes
+ * component hits, shared hits, and the seed hit.
+ * @return Returns the number of component hits in the cluster
+ * as an <code>int</code>.
+ */
+ public int getHitCount() { return hitList.size() + shareList.size() + 1; }
+
+ /**
+ * <b>getComponentHitCount</b><br/><br/>
+ * <code>public int <b>getComponentHitCount</b>()</code><br/><br/>
+ * Indicates how many component hits compose this cluster. Note
+ * that this does not include the seed hit or shared hits.
+ * @return Returns the number of component hits in the cluster
+ * as an <code>int</code>.
+ */
+ public int getComponentHitCount() { return shareList.size(); }
+
+ /**
+ * <b>getSharedHitCount</b><br/><br/>
+ * <code>public int <b>getSharedHitCount</b>()</code><br/><br/>
+ * Indicates how many shared hits compose this cluster. Note that
+ * this does not include the seed hit or component hits.
+ * @return Returns the number of shared hits in the cluster as an
+ * <code>int</code>.
+ */
+ public int getSharedHitCount() { return hitList.size() + 1; }
+}
java/trunk/monitoring-app/src/main/java/org/hps/monitoring/ecal
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/ecal/Datum.java 2014-02-25 04:08:56 UTC (rev 254)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/ecal/Datum.java 2014-02-25 16:44:47 UTC (rev 255)
@@ -34,7 +34,7 @@
* <b>getX</b><br/><br/>
* <code>public int <b>getX</b>()</code><br/><br/>
* Indicates the x-coordinate of the object.
- * @return Returns the x-cooridinate as an <code>int</code>.
+ * @return Returns the x-coordinate as an <code>int</code>.
**/
public int getX() { return loc.x; }
@@ -42,7 +42,7 @@
* <b>getY</b><br/><br/>
* <code>public int <b>getY</b>()</code><br/><br/>
* Indicates the y-coordinate of the object.
- * @return Returns the y-coordiate as an <code>int</code>.
+ * @return Returns the y-coordinate as an <code>int</code>.
**/
public int getY() { return loc.y; }
java/trunk/monitoring-app/src/main/java/org/hps/monitoring/ecal
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/ecal/EcalPanel.java 2014-02-25 04:08:56 UTC (rev 254)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/ecal/EcalPanel.java 2014-02-25 16:44:47 UTC (rev 255)
@@ -1,12 +1,10 @@
package org.hps.monitoring.ecal;
-import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
-import java.awt.Graphics2D;
-import java.awt.geom.Line2D;
+import java.awt.Point;
import java.text.DecimalFormat;
import java.text.NumberFormat;
@@ -24,6 +22,8 @@
private static final long serialVersionUID = 6292751227464151897L;
// The color used for rendering seed hits.
private Color clusterColor = Color.GREEN;
+ // The default color of the calorimeter crystals.
+ private Color defaultColor = null;
// The color-mapping scale used by to color calorimeter crystals.
private MultiGradientScale scale = MultiGradientScale.makeRainbowScale(0.0, 1.0);
// The number of boxes in the x-direction.
@@ -32,26 +32,25 @@
private int yBoxes = 1;
// The width of the scale.
private int scaleWidth = 75;
- // Whether the scale has changed or not since its last rendering.
- private boolean scaleChanged = true;
// Stores which calorimeter crystals are disabled.
private boolean[][] disabled;
// Stores the energies in each calorimeter crystal.
private double[][] hit;
// Stores whether a crystal is the location of a seed hit.
private boolean[][] cluster;
- // Stores whether a crystal has changed.
- private boolean changed[][];
- // Stores whether the panel size has chaged.
- private boolean sizeChanged = true;
+ // Stores what color to highlight the crystal with.
+ private Color[][] highlight;
// The panel on which the scale is rendered.
- ScalePanel scalePanel = new ScalePanel();
+ private ScalePanel scalePanel = new ScalePanel();
+ // Store the size of the panel as of the last refresh.
+ private int[] lastSize = new int[2];
// Efficiency variables for crystal placement.
- int boxWidth = 0;
- int widthRem = 0;
- int boxHeight = 0;
- int heightRem = 0;
+ private int[] widths;
+ private int[] heights;
+ private int[] xPosition;
+ private int[] yPosition;
+ private int[] clusterSpace = new int[3];
/**
* <b>EcalPanel</b><br/><br/>
@@ -67,17 +66,27 @@
xBoxes = numXBoxes;
yBoxes = numYBoxes;
- // Initialize the arrays.
+ // Initialize data the arrays.
disabled = new boolean[xBoxes][yBoxes];
hit = new double[xBoxes][yBoxes];
cluster = new boolean[xBoxes][yBoxes];
- changed = new boolean[xBoxes][yBoxes];
+ highlight = new Color[xBoxes][yBoxes];
+ for(int x = 0; x < xBoxes; x++) {
+ for(int y = 0; y < yBoxes; y++) {
+ highlight[x][y] = null;
+ }
+ }
+
+ // Initialize the size arrays,
+ widths = new int[xBoxes];
+ heights = new int[yBoxes];
+ xPosition = new int [xBoxes + 1];
+ yPosition = new int[yBoxes + 1];
+
// Add the scale panel.
setLayout(null);
add(scalePanel);
- sizeChanged = true;
- scaleChanged = true;
}
/**
@@ -95,7 +104,6 @@
public void setCrystalEnabled(int xIndex, int yIndex, boolean active) throws IndexOutOfBoundsException {
if (xIndex >= 0 && xIndex < xBoxes && yIndex >= 0 && yIndex < yBoxes) {
disabled[xIndex][yIndex] = !active;
- changed[xIndex][yIndex] = true;
}
else {
throw new IndexOutOfBoundsException(String.format("Invalid crystal address (%2d, %2d).", xIndex, yIndex));
@@ -116,7 +124,6 @@
public void addCrystalEnergy(int xIndex, int yIndex, double energy) throws IndexOutOfBoundsException {
if (xIndex >= 0 && xIndex < xBoxes && yIndex >= 0 && yIndex < yBoxes) {
this.hit[xIndex][yIndex] += energy;
- changed[xIndex][yIndex] = true;
}
else {
throw new IndexOutOfBoundsException(String.format("Invalid crystal address (%2d, %2d).", xIndex, yIndex));
@@ -137,7 +144,6 @@
public void setCrystalCluster(int xIndex, int yIndex, boolean cluster) throws IndexOutOfBoundsException {
if (xIndex >= 0 && xIndex < xBoxes && yIndex >= 0 && yIndex < yBoxes) {
this.cluster[xIndex][yIndex] = cluster;
- changed[xIndex][yIndex] = true;
}
else {
throw new IndexOutOfBoundsException(String.format("Invalid crystal address (%2d, %2d).", xIndex, yIndex));
@@ -145,27 +151,52 @@
}
/**
+ * <b>setCrystalHighlight</b><br/><br/>
+ * <code>public void <b>setCrystalHighlight</b>(int xIndex, int yIndex, Color highlight)</code><br/><br/>
+ * @param xIndex - The x-coordinate of the crystal.
+ * @param yIndex - The y-coordinate of the crystal.
+ * @param highlight - The color which the indicated crystal should
+ * be highlighted. A value of <code>null</code> indicates that no
+ * highlight should be used.
+ * @throws IndexOutOfBoundsException Occurs when the given xy
+ * crystal coordinate does not point to a crystal.
+ */
+ public void setCrystalHighlight(int xIndex, int yIndex, Color highlight) throws IndexOutOfBoundsException {
+ if (xIndex >= 0 && xIndex < xBoxes && yIndex >= 0 && yIndex < yBoxes) {
+ this.highlight[xIndex][yIndex] = highlight;
+ }
+ else {
+ throw new IndexOutOfBoundsException(String.format("Invalid crystal address (%2d, %2d).", xIndex, yIndex));
+ }
+ }
+
+ /**
* <b>clearCrystals</b><br/><br/>
* <code>public void <b>clearCrystals</b>()</code><br/><br/>
- * Sets all crystal energies to zero and removes all clusters. This <b>does
- * not</b> enable any disabled crystals.
+ * Sets all crystal energies to zero and removes all clusters. This
+ * <b>does not</b> enable disabled crystals.
**/
public void clearCrystals() {
for (int x = 0; x < xBoxes; x++) {
for (int y = 0; y < yBoxes; y++) {
- if (hit[x][y] != 0.0) {
- hit[x][y] = 0.0;
- changed[x][y] = true;
- }
- if (cluster[x][y]) {
- cluster[x][y] = false;
- changed[x][y] = true;
- }
+ hit[x][y] = 0.0;
+ cluster[x][y] = false;
}
}
}
/**
+ * <b>clearHighlight</b><br/><br/>
+ * <code>public void <b>clearHighlight</b>()</code><br/><br/>
+ * Clears any highlighting on the crystals.
+ */
+ public void clearHighlight() {
+ for (int x = 0; x < xBoxes; x++) {
+ for (int y = 0; y < yBoxes; y++) { highlight[x][y] = null; }
+ }
+ }
+
+ /**
* <b>setClusterColor</b><br/><br/>
* <code>public void <b>setClusterColor</b>(Color c)</code><br/><br/>
* Sets the color of the seed hit marker.
@@ -184,7 +215,6 @@
**/
public void setMinimum(double minimum) {
scale.setMinimum(minimum);
- scaleChanged = true;
}
/**
@@ -196,7 +226,6 @@
**/
public void setMaximum(double maximum) {
scale.setMaximum(maximum);
- scaleChanged = true;
}
/**
@@ -206,20 +235,55 @@
**/
public void setScalingLinear() {
scale.setScalingLinear();
- scaleChanged = true;
}
/**
* <b>setScalingLogarithmic</b><br/><br/>
- * <code>public void <b>setScalingLogarithmic</b></code><br/><br/>
+ * <code>public void <b>setScalingLogarithmic</b>()</code><br/><br/>
* Sets the color mapping scale behavior to logarithmic mapping.
**/
public void setScalingLogarithmic() {
scale.setScalingLogarithmic();
- scaleChanged = true;
}
/**
+ * <b>isScalingLinear</b><br/><br/>
+ * <code>public void <b>isScalingLinear</b></code>()<br/><br/>
+ * Indicates whether the crystal colors are mapped linearly.
+ * @return Returns <code>true</code> if the mapping is linear
+ * and <code>false</code> otherwise.
+ */
+ public boolean isScalingLinear() { return scale.isLinearScale(); }
+
+ /**
+ * <b>isScalingLogarithmic</b><br/><br/>
+ * <code>public void <b>isScalingLogarithmic</b></code>()<br/><br/>
+ * Indicates whether the crystal colors are mapped logarithmically.
+ * @return Returns <code>true</code> if the mapping is logarithmic
+ * and <code>false</code> otherwise.
+ */
+ public boolean isScalingLogarithmic() { return scale.isLogairthmicScale(); }
+
+ /**
+ * <b>isCluster</b><br/><br/>
+ * <code>public boolean <b>isCluster</b></code>()<br/><br/>
+ * Determines if the crystal at the given coordinates is a cluster
+ * center or not.
+ * @param xCoor - The x-coordinate of the crystal.
+ * @param yCoor - The y-coordinate of the crystal.
+ * @return Returns <code>true</code> if the crystal is a cluster
+ * center and <code>false</code> if it is not or if the indices
+ * are invalid.
+ */
+ public boolean isCluster(int xCoor, int yCoor) {
+ // If the coordinates are invalid, return false.
+ if(!validateIndices(xCoor, yCoor)) { return false; }
+
+ // Otherwise, check if it is a cluster.
+ else { return cluster[xCoor][yCoor]; }
+ }
+
+ /**
* <b>setScaleEnabled</b><br/><br/>
* <code>public void <b>setScaleEnabled</b>(boolean enabled)</code><br/><br/>
* Sets whether the scale should be visible or not.
@@ -229,12 +293,90 @@
public void setScaleEnabled(boolean enabled) {
if (scalePanel.isVisible() != enabled) {
scalePanel.setVisible(enabled);
- scaleChanged = true;
- sizeChanged = true;
}
}
/**
+ * <b>setCrystalDefaultColor</b><br/><br/>
+ * <code>public void <b>setCrystalDefaultColor</b>(Color c)</code><br/><br/>
+ * Sets the color that crystals with zero energy will display.
+ * @param c - The color to use for zero energy crystals. A value
+ * of <code>null</code> will use the appropriate energy color
+ * map value.
+ */
+ public void setCrystalDefaultColor(Color c) { defaultColor = c; }
+
+ /**
+ * <b>getCrystalID</b><br/><br/>
+ * <code>public Point <b>getCrystalID</b>(int xCoor, int yCoor)</code><br/><br/>
+ * Determines the panel crystal index of the crystal at the given
+ * panel coordinates.
+ * @param xCoor - The x-coordinate on the panel.
+ * @param yCoor - The y-coordinate on the panel.
+ * @return Returns a <code>Point</code> object containing the panel
+ * crystal indices of the crystal at the given panel coordinates.
+ * Returns <code>null</code> if the coordinates do not map to a crystal.
+ */
+ public Point getCrystalID(int xCoor, int yCoor) {
+ // If either coordinate is negative, return the null result.
+ if(xCoor < 0 || yCoor < 0) { return null; }
+
+ // If either coordinate is too large, return the nul result.
+ if(xCoor > xPosition[xBoxes] || yCoor > yPosition[yBoxes]) {
+ return null;
+ }
+
+ // Make a point to identify the crystal index.
+ Point loc = new Point(-1, -1);
+
+ // Determine which y index it is.
+ for(int y = 0; y < yBoxes; y++) {
+ if(yCoor <= yPosition[y + 1]) {
+ loc.y = y;
+ break;
+ }
+ }
+
+ // Determine which x index it is.
+ for(int x = 0; x < xBoxes; x++) {
+ if(xCoor <= xPosition[x + 1]) {
+ loc.x = x;
+ break;
+ }
+ }
+
+ // If either coordinate is not valid, return null.
+ if(loc.x == -1 || loc.y == -1) { return null; }
+
+ // Return the crystal identifier.
+ return loc;
+ }
+
+ /**
+ * <b>getCrystalEnergy</b><br/><br/>
+ * <code>public double <b>getCrystalEnergy</b>(int ix, int iy)</code><br/><br/>
+ * Provides the energy stored in the indicated crystal.
+ * @param ix - The crystal's x-index.
+ * @param iy - The crystal's y-index.
+ * @return Returns the energy as a <code>double</code>.
+ * @throws IndexOutOfBoundsException - Occurs when either of the
+ * given indices are invalid.
+ */
+ public double getCrystalEnergy(int ix, int iy) throws IndexOutOfBoundsException {
+ if(!validateIndices(ix, iy)) {
+ throw new IndexOutOfBoundsException("Invalid crystal index.");
+ }
+ else { return hit[ix][iy]; }
+ }
+
+ public Color getCrystalHighlight(int ix, int iy) throws IndexOutOfBoundsException {
+ if(!validateIndices(ix, iy)) {
+ throw new IndexOutOfBoundsException("Invalid crystal index.");
+ }
+ else { return highlight[ix][iy]; }
+ }
+
+ /**
* <b>redraw</b><br/><br/>
* <code>public void <b>redraw</b>()</code> Re-renders the calorimeter
* panel.
@@ -247,10 +389,20 @@
super.setSize(width, height);
scalePanel.setLocation(width - scaleWidth, 0);
scalePanel.setSize(scaleWidth, height);
- sizeChanged = true;
}
protected void paintComponent(Graphics g) {
+ // Check to see if the panel has changed sizes since the last
+ // time it was rendered.
+ boolean sizeChanged = false;
+ if(getWidth() != lastSize[0] || getHeight() != lastSize[1]) {
+ lastSize[0] = getWidth();
+ lastSize[1] = getHeight();
+ sizeChanged = true;
+ }
+
+ // If the size of the panel has changed, we need to update
+ // the crystal locations.
if (sizeChanged) {
// Determine the width and heights of the calorimeter crystals.
int width;
@@ -258,118 +410,119 @@
else { width = getWidth(); }
int height = getHeight();
- boxWidth = width / xBoxes;
- widthRem = width % xBoxes;
- boxHeight = height / yBoxes;
- heightRem = height % yBoxes;
+ int boxWidth = width / xBoxes;
+ int widthRem = width % xBoxes;
+ int boxHeight = height / yBoxes;
+ int heightRem = height % yBoxes;
+
+ // Store the widths for each crystal.
+ for(int x = 0; x < xBoxes; x++) {
+ widths[x] = boxWidth;
+ if(widthRem > 0) {
+ widths[x]++;
+ widthRem--;
+ }
+ xPosition[x + 1] = xPosition[x] + widths[x];
+ }
+
+ // Store the height for each crystal.
+ for(int y = 0; y < yBoxes; y++) {
+ heights[y] = boxHeight;
+ if(heightRem > 0) {
+ heights[y]++;
+ heightRem--;
+ }
+ yPosition[y + 1] = yPosition[y] + heights[y];
+ }
+
+ // Calculate the cluster position variables.
+ double ltw = 0.25 * boxWidth;
+ double lth = 0.25 * boxHeight;
+
+ if(ltw > lth) {
+ clusterSpace[0] = (int)Math.round((boxWidth - lth - lth) / 2.0);
+ clusterSpace[1] = (int)Math.round(lth);
+ clusterSpace[2] = (int)Math.round(lth + lth);
+
+ }
+ else {
+ clusterSpace[0] = (int)Math.round(ltw);
+ clusterSpace[1] = (int)Math.round((boxHeight - ltw - ltw) / 2.0);
+ clusterSpace[2] = (int)Math.round(ltw + ltw);
+
+ }
}
- int heightRemReset = heightRem;
- int widthRemReset = widthRem;
- // Start drawing the calorimeter crystals. To avoid having empty
- // space, we distribute the extra widthRem pixels to the boxes at
- // a rate of one pixel for box until we run out. We do the same thing
- // for the heightRem.
- int curX = 0;
- int curY = 0;
+ // Render the crystals at the locations calculated in the size
+ // change block.
for (int x = 0; x < xBoxes; x++) {
- // Determine if this column should use an extra pixel.
- int tw = boxWidth;
- if (widthRem != 0) {
- tw++;
- widthRem--;
- }
for (int y = 0; y < yBoxes; y++) {
- // Determine if this row should use an extra pixel.
- int th = boxHeight;
- if (heightRem != 0) {
- th++;
- heightRem--;
+ // Determine the appropriate color for the box.
+ Color crystalColor;
+ if (disabled[x][y]) { crystalColor = Color.BLACK; }
+ else if(defaultColor != null && hit[x][y] == 0) { crystalColor = defaultColor; }
+ else { crystalColor = scale.getColor(hit[x][y]); }
+ g.setColor(crystalColor);
+
+ // Draw the crystal energy color.
+ g.fillRect(xPosition[x], yPosition[y], widths[x], heights[y]);
+
+ // Draw the crystal border.
+ g.setColor(Color.BLACK);
+ g.drawRect(xPosition[x], yPosition[y], widths[x] - 1, heights[y] - 1);
+
+ // Draw a highlight, if needed.
+ if(highlight[x][y] != null && !disabled[x][y]) {
+ g.setColor(highlight[x][y]);
+ g.drawRect(xPosition[x] + 1, yPosition[y] + 1, widths[x] - 3, heights[y] - 3);
}
- if (sizeChanged || scaleChanged || changed[x][y]) {
- // Determine the appropriate color for the box.
- Color crystalColor;
- if (disabled[x][y]) { crystalColor = Color.BLACK; }
- else { crystalColor = scale.getColor(hit[x][y]); }
- g.setColor(crystalColor);
-
- // Draw the box.
- g.fillRect(curX, curY, tw, th);
- g.setColor(Color.BLACK);
- g.drawRect(curX, curY, tw, th);
-
- // If there is a cluster, draw an x.
- if (cluster[x][y]) {
- // Get the correct coordinates.
- double ltw = (0.3 * tw) / 2;
- double lth = (0.5 * th) / 2;
- double[] lx = { curX + ltw, curX + tw - ltw };
- double[] ly = { curY + lth, curY + th - lth };
-
- // Get the appropriate cluster color.
- Color c;
- if (clusterColor == null) {
- int red = Math.abs(255 - crystalColor.getRed());
- int blue = Math.abs(255 - crystalColor.getBlue());
- int green = Math.abs(255 - crystalColor.getGreen());
- c = new Color(red, green, blue);
- }
- else { c = clusterColor; }
-
- // Draw an x on the cluster crystal.
- Graphics2D g2 = (Graphics2D) g;
- g2.setColor(c);
- // g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
- // RenderingHints.VALUE_ANTIALIAS_ON);
- g2.setStroke(new BasicStroke(2));
- g2.draw(new Line2D.Double(lx[0], ly[0], lx[1], ly[1]));
- g2.draw(new Line2D.Double(lx[0], ly[1], lx[1], ly[0]));
- // g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
- // RenderingHints.VALUE_ANTIALIAS_OFF);
+ // If there is a cluster, draw a circle.
+ if (cluster[x][y]) {
+ // Get the appropriate cluster color.
+ Color c;
+ if (clusterColor == null) {
+ int red = Math.abs(255 - crystalColor.getRed());
+ int blue = Math.abs(255 - crystalColor.getBlue());
+ int green = Math.abs(255 - crystalColor.getGreen());
+ c = new Color(red, green, blue);
}
+ else { c = clusterColor; }
- // Note that this crystals has been updated.
- changed[x][y] = false;
+ // Draw an circle on the cluster crystal.
+ g.setColor(c);
+ g.fillOval(xPosition[x] + clusterSpace[0], yPosition[y] + clusterSpace[1],
+ clusterSpace[2], clusterSpace[2]);
}
-
- // Increment the current y position.
- curY += th;
- }
-
- // Increment the current x position.
- curX += tw;
-
- // Reset the current y position and heightRem.
- curY = 0;
- heightRem = heightRemReset;
+ }
}
-
- // If the scale has changed, redraw the scale panel as well.
- if (scaleChanged && scalePanel.isVisible()) {
- scalePanel.redraw();
- }
-
- // Indicate that the any size changes have been handled.
- scaleChanged = false;
- sizeChanged = false;
-
- // Reset the height and width remainder variables.
- heightRem = heightRemReset;
- widthRem = widthRemReset;
}
/**
+ * <b>validateIndices</b><br/><br/>
+ * <code>private boolean <b>validateIndices</b>(int ix, int iy)</code><br/><br/>
+ * Indicates whether the given indices corresponds to a valid
+ * crystal or not.
+ * @param ix - The crystal's x index.
+ * @param iy - The crystal's y index.
+ * @return Returns <code>true</code> if the indices are valid
+ * and <code>false</code> if they are not.
+ */
+ private boolean validateIndices(int ix, int iy) {
+ boolean lowX = (ix > -1);
+ boolean highX = (ix < xBoxes);
+ boolean lowY = (iy > -1);
+ boolean highY = (iy < yBoxes);
+
+ return (lowX && highX && lowY && highY);
+ }
+
+ /**
* The local class <b>ScalePanel</b> renders the scale for the calorimeter
* color map.
**/
private class ScalePanel extends JPanel {
- /**
- * <b>redraw</b><br/><br/>
- * <code>public void <b>redraw</b>()</code><br/><br/>
- * Orders the scale to re-render itself.
- **/
- public void redraw() { super.repaint(); }
+ private static final long serialVersionUID = -2644562244208528609L;
protected void paintComponent(Graphics g) {
// Set the text region width.
@@ -433,21 +586,7 @@
// Determine the spacing of the text.
FontMetrics fm = g.getFontMetrics(g.getFont());
int fontHeight = fm.getHeight();
- double fStep = (height - 2.0 * fontHeight) / fontHeight;
- double halfStep = fStep / 2.0;
- // Get the scaling value.
- double fScale;
- double fMin;
- if (linear) {
- fScale = scale.getMaximum() - scale.getMinimum();
- fMin = scale.getMinimum();
- }
- else {
- fScale = Math.log10(scale.getMaximum() - Math.log10(scale.getMinimum()));
- fMin = Math.log10(scale.getMinimum());
- }
-
// Populate the first and last values.
NumberFormat nf = new DecimalFormat("0.#E0");
g.setColor(Color.WHITE);
java/trunk/monitoring-app/src/main/java/org/hps/monitoring/ecal
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/ecal/EventManager.java 2014-02-25 04:08:56 UTC (rev 254)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/ecal/EventManager.java 2014-02-25 16:44:47 UTC (rev 255)
@@ -31,7 +31,7 @@
// List for storing the hits from the current event.
private ArrayList<EcalHit> hitList = new ArrayList<EcalHit>();
// List for storing the clusters from the current hit.
- private ArrayList<Datum> clusterList = new ArrayList<Datum>();
+ private ArrayList<Cluster> clusterList = new ArrayList<Cluster>();
// Whether the event manager has an open file.
private boolean open = true;
@@ -82,15 +82,37 @@
int ix = Integer.parseInt(st.nextToken());
int iy = Integer.parseInt(st.nextToken());
- // Convert it to an object.
- if (name.compareTo("Cluster") == 0) {
- clusterList.add(new Datum(ix, iy));
- }
+ // If this is a cluster, add a new cluster object.
+ if (name.compareTo("Cluster") == 0) { clusterList.add(new Cluster(ix, iy)); }
+
+ // If this is a calorimeter hit, add a new calorimeter hit object.
else if (name.compareTo("EcalHit") == 0) {
double energy = Double.parseDouble(st.nextToken());
hitList.add(new EcalHit(ix, iy, energy));
}
+ // If this is a cluster component hit, add it to the last cluster.
+ else if(name.compareTo("CompHit") == 0) {
+ // There must be a last cluster to process this hit type.
+ if(clusterList.size() == 0) {
+ System.err.println("File Format Error: A cluster component hit was read, but" +
+ " no cluster has been declared. Terminating.");
+ System.exit(1);
+ }
+ else { clusterList.get(clusterList.size() - 1).addComponentHit(ix, iy); }
+ }
+
+ // If this is a cluster shared hit, add it to the last cluster.
+ else if(name.compareTo("SharHit") == 0) {
+ // There must be a last cluster to process this hit type.
+ if(clusterList.size() == 0) {
+ System.err.println("File Format Error: A cluster shared hit was read, but" +
+ " no cluster has been declared. Terminating.");
+ System.exit(1);
+ }
+ else { clusterList.get(clusterList.size() - 1).addSharedHit(ix, iy); }
+ }
+
// Get the next line.
curLine = reader.readLine();
}
@@ -125,12 +147,12 @@
/**
* <b>getClusters</b><br/><br/>
- * <code>public ArrayList<Datum> <b>getClusters</b></code><br/><br/>
+ * <code>public ArrayList<Cluster> <b>getClusters</b></code><br/><br/>
* Allows access to the current event's list of clusters.
* @return Returns the current clusters as an <code>ArrayList
* </code> object.
**/
- public ArrayList<Datum> getClusters() {
+ public ArrayList<Cluster> getClusters() {
if (!open) { return null; }
else { return clusterList; }
}
java/trunk/monitoring-app/src/main/java/org/hps/monitoring/ecal
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/ecal/Main.java 2014-02-25 04:08:56 UTC (rev 254)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/ecal/Main.java 2014-02-25 16:44:47 UTC (rev 255)
@@ -26,9 +26,12 @@
(screenHeight - window.getPreferredSize().height) / 2);
window.setDataSource("cluster-hit.txt");
window.displayNextEvent();
+
+ /**
+ int key = 0;
+ while((key = System.in.read()) != 10) { }
+ **/
window.setVisible(true);
-
- // makeData();
}
static void makeData() {
java/trunk/monitoring-app/src/main/java/org/hps/monitoring/ecal
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/ecal/StatusPanel.java (rev 0)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/ecal/StatusPanel.java 2014-02-25 16:44:47 UTC (rev 255)
@@ -0,0 +1,170 @@
+package org.hps.monitoring.ecal;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Graphics;
+
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+/**
+ * Class <code>StatusPanel</code> displays text in a set of fields.
+ *
+ *@author Kyle McCarty
+ */
+public class StatusPanel extends JPanel {
+ private static final long serialVersionUID = -8353479383875379010L;
+ private int leftBuffer = 10;
+ private int upperBuffer = 10;
+ private BackPanel background = new BackPanel();
+ private JLabel[][] field;
+ private static final String nullValue = "---";
+
+ /**
+ * <b>StatusPanel</b><br/><br/>
+ * <code>public <b>StatusPanel</b>(String... fieldName)</code><br/><br/>
+ * Creates a new status panel with display fields with the indicated
+ * names. They will be assigned a field index in the order that they
+ * are given starting with zero.
+ * @param fieldName - The names of the fields to display.
+ */
+ public StatusPanel(String... fieldName) {
+ // Initialize the component.
+ super();
+
+ // Set the layout manager to manual.
+ setLayout(null);
+
+ // Build the text fields.
+ int curZ = 0;
+ field = new JLabel[fieldName.length][2];
+ for(int i = 0; i < field.length; i++) {
+ for(int j = 0; j < field[i].length; j++) {
+ field[i][j] = new JLabel();
+ field[i][j].setOpaque(true);
+ field[i][j].setBackground(Color.WHITE);
+ add(field[i][j]);
+ setComponentZOrder(field[i][j], curZ);
+ curZ++;
+ }
+ field[i][0].setText(fieldName[i] + ":");
+ }
+
+ // Start the fields as null by default.
+ clearValues();
+
+ // Build the background panel.
+ add(background);
+ setComponentZOrder(background, curZ);
+ }
+
+ /**
+ * <b>setFieldValue</b><br/><br/>
+ * Sets the value of the indicated field.
+ * @param index - The field's index.
+ * @param value - The new value to display.
+ * @throws IndexOutOfBoundsException Occurs when the field index
+ * is neither more than the existing number of fields or is negative.
+ */
+ public void setFieldValue(int index, String value) throws IndexOutOfBoundsException {
+ if(index >= 0 && index < field.length) {
+ if(value == null) { field[index][1].setText(nullValue); }
+ else { field[index][1].setText(value); }
+ }
+ else { throw new IndexOutOfBoundsException("Invalid field index."); }
+ }
+
+ public void setSize(int width, int height) {
+ super.setSize(width, height);
+ resize();
+ }
+
+ public void setSize(Dimension d) {
+ super.setSize(d);
+ resize();
+ }
+
+ /**
+ * <b>clearValues</b><br/><br/>
+ * <code>public void <b>clearValues</b>()</code><br/><br/>
+ * Sets all of the fields on the status display to the null value.
+ */
+ public void clearValues() {
+ for(int i = 0; i < field.length; i++) {
+ field[i][1].setText(nullValue);
+ }
+ }
+
+ private void resize() {
+ // Define the width an height as convenience variables.
+ int width = getWidth();
+ int height = getHeight();
+
+ // Size the background panel.
+ background.setBounds(0, 0, width, height);
+
+ // Size and place the text labels.
+ if(field.length != 0) {
+ int labelHeight = (height - (int)(upperBuffer + 5)) / field.length;
+ int labelRem = (height - upperBuffer - 8) % field.length;
+ int curY = (int)(upperBuffer + 2);
+ for(int i = 0; i < field.length; i++) {
+ // Determine the appropriate field height.
+ int thisHeight = labelHeight;
+ if(labelRem > 0) {
+ thisHeight++;
+ labelRem--;
+ }
+
+ // Place the field.
+ field[i][0].setBounds(leftBuffer, curY, 65, thisHeight);
+ field[i][1].setBounds(getNextX(field[i][0]), curY, 100, thisHeight);
+
+ // Increment the current position.
+ curY += thisHeight;
+ }
+ }
+ }
+
+ /**
+ *<b>getNextX</b><br/><br/>
+ * <code>private int <b>getNextX</b>(Component c)</code><br/><br/>
+ * Finds the x-coordinate immediately after the component.
+ * @param c - The component of which to find the end.
+ * @return Returns the x-coordinate at the end of the component.
+ */
+ private final static int getNextX(Component c) { return getNextX(c, 0); }
+
+ /**
+ /**
+ *<b>getNextX</b><br/><br/>
+ * <code>private int <b>getNextX</b>(Component c, int buffer)</code><br/><br/>
+ * Finds the x-coordinate after the component with a given buffer.
+ * @param c - The component of which to find the end.
+ * @param buffer - The extra space after the component to be included.
+ * @return Returns the x-coordinate at the end of the component,
+ * with a buffer length.
+ */
+ private final static int getNextX(Component c, int buffer) {
+ return c.getX() + c.getWidth() + buffer;
+ }
+
+ /**
+ * Class <code>BackPanel</code> simply renders the background panel
+ * for the status panel.
+ */
+ private class BackPanel extends JPanel {
+ private static final long serialVersionUID = 4997805650267243080L;
+
+ public void paint(Graphics g) {
+ // Render the panel background.
+ g.setColor(Color.WHITE);
+ g.fillRect(0, upperBuffer, getWidth(), getHeight() - upperBuffer);
+ g.setColor(Color.GRAY);
+ g.drawRect(0, upperBuffer, getWidth() - 1, getHeight() - upperBuffer - 1);
+ g.setColor(Color.LIGHT_GRAY);
+ g.drawRect(1, upperBuffer + 1, getWidth() - 3, getHeight() - upperBuffer - 3);
+ }
+ }
+}
java/trunk/monitoring-app/src/main/java/org/hps/monitoring/ecal
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/ecal/Viewer.java 2014-02-25 04:08:56 UTC (rev 254)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/ecal/Viewer.java 2014-02-25 16:44:47 UTC (rev 255)
@@ -1,11 +1,18 @@
package org.hps.monitoring.ecal;
+import java.awt.Color;
import java.awt.Dimension;
+import java.awt.Point;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
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.io.IOException;
+import java.text.DecimalFormat;
+import java.util.HashMap;
import java.util.List;
import javax.swing.JFrame;
@@ -25,11 +32,32 @@
// Java-suggested variable.
private static final long serialVersionUID = -2022819652687941812L;
// The calorimeter panel.
- private static final EcalPanel ecalPanel = new EcalPanel(46, 11);
+ private final EcalPanel ecalPanel = new EcalPanel(46, 11);
+ // The crystal status panel.
+ private final StatusPanel statusPanel = new StatusPanel("x Index", "y Index", "Energy");
// The event data reader.
private EventManager em = null;
- // Whether an LCIO event is being processed.
- private boolean processing = false;
+ // Map the cluster location to the cluster object.
+ private HashMap<Point, Cluster> clusterMap = new HashMap<Point, Cluster>();
+ // Whether crystal should be highlighted when hovered over.
+ private boolean highlight = true;
+ // Store the last crystal to be highlighted.
+ private Point lastCrystal = null;
+ // DEPRECATED :: Store the old highlight color.
+ //private Color oldHighlight = null;
+ // DEPRECATED :: Store the currently highlighted cluster.
+ //private Point lastCluster = null;
+ // Stores whether the background color is set or not.
+ private boolean background = false;
+ // Define the highlight color for dark backgrounds.
+ private static final Color HIGHLIGHT_CURSOR_DARK = new Color(90, 170, 250);
+ // Define the highlight color for light backgrounds.
+ private static final Color HIGHLIGHT_CURSOR_LIGHT = Color.BLUE;
+ // Define the highlight color for cluster component hits.
+ private static final Color HIGHLIGHT_CLUSTER_COMPONENT = Color.RED;
+ // Define the highlight color for cluster shared hits.
+ private static final Color HIGHLIGHT_CLUSTER_SHARED = Color.YELLOW;
+ private boolean processing = false;
/**
* <b>Viewer</b><br/><br/>
@@ -42,15 +70,15 @@
setTitle("HPS Ecal Cluster Viewer");
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setPreferredSize(new Dimension(1060, 600));
- setMinimumSize(new Dimension(1060, 400));
+ setMinimumSize(new Dimension(1060, 525));
setLayout(null);
// Set the scaling settings.
- ecalPanel.setMinimum(0.001);
+ ecalPanel.setMinimum(0.0001);
ecalPanel.setMaximum(3000);
ecalPanel.setScalingLogarithmic();
- // Disable the crystals in the ecal panel along the beam gap.
+ // Disable the crystals in the calorimeter panel along the beam gap.
for (int i = -23; i < 24; i++) {
ecalPanel.setCrystalEnabled(getPanelX(i), 5, false);
if (i > -11 && i < -1) {
@@ -60,10 +88,15 @@
}
// Make a key listener to change events.
- addKeyListener(new EcalListener());
+ addKeyListener(new EcalKeyListener());
- // Add the ecal pane
+ // Make a mouse motion listener to monitor mouse hovering.
+ getContentPane().addMouseListener(new EcalMouseListener());
+ getContentPane().addMouseMotionListener(new EcalMouseMotionListener());
+
+ // Add the panels.
add(ecalPanel);
+ add(statusPanel);
// Add a listener to update everything when the window changes size
addComponentListener(new ResizeListener());
@@ -89,13 +122,52 @@
em = new EventManager(filepath);
}
+ /**
+ * <b>displayNextEvent</b><br/><br/>
+ * <code>public void <b>displayNextEvent</b>()</code><br/><br/>
+ * Feeds the calorimeter panel the data from the next event.
+ * @throws IOException Occurs when there is an issue with reading the data file.
+ **/
+ public void displayNextEvent() throws IOException {
+ // Clear the calorimeter panel.
+ ecalPanel.clearCrystals();
+ ecalPanel.clearHighlight();
+
+ // Clear the cluster map and cluster highlighting.
+ clusterMap.clear();
+ resetCursor();
+
+ // If there is no data source, we can not do anything.
+ if (em == null) { return; }
+
+ // Otherwise, get the next event.
+ em.readEvent();
+
+ // Display it.
+ for (EcalHit h : em.getHits()) {
+ int ix = getPanelX(h.getX());
+ int iy = getPanelY(h.getY());
+ ecalPanel.addCrystalEnergy(ix, iy, h.getEnergy());
+ }
+ for (Cluster c : em.getClusters()) {
+ Point seedHit = c.getSeedHit();
+ int ix = getPanelX(seedHit.x);
+ int iy = getPanelY(seedHit.y);
+ ecalPanel.setCrystalCluster(ix, iy, true);
+ clusterMap.put(new Point(getPanelX(seedHit.x), getPanelY(seedHit.y)), c);
+ }
+
+ // Redraw the calorimeter panel.
+ ecalPanel.redraw();
+ }
+
public void displayLCIOEvent(EventHeader event, String ecalCollectionName, String clusterCollectionName) {
// Make sure that a draw is not in process.
if(processing) { return; }
-
+
// Otherwise, we are now processing.
processing = true;
-
+
// Get the list of clusters and hits.
List<HPSEcalCluster> clusters = event.get(HPSEcalCluster.class, clusterCollectionName);
List<HPSCalorimeterHit> hits = event.get(HPSCalorimeterHit.class, ecalCollectionName);
@@ -127,103 +199,250 @@
}
/**
- * <b>displayNextEvent</b><br/><br/>
- * <code>public void <b>displayNextEvent</b>()</code><br/><br/>
- * Feeds the calorimeter panel the data from the next event.
- * @throws IOException Occurs when there is an issue with reading the data file.
- **/
- public void displayNextEvent() throws IOException {
- // Clear the ecal panel.
- ecalPanel.clearCrystals();
-
- // If there is no data source, we can not do anything.
- if (em == null) { return; }
-
- // Otherwise, get the next event.
- em.readEvent();
-
- // Display it.
- for (EcalHit h : em.getHits()) {
- int ix = getPanelX(h.getX());
- int iy = getPanelY(h.getY());
- ecalPanel.addCrystalEnergy(ix, iy, h.getEnergy());
- }
- for (Datum d : em.getClusters()) {
- int ix = getPanelX(d.getX());
- int iy = getPanelY(d.getY());
- ecalPanel.setCrystalCluster(ix, iy, true);
- }
-
- // Redraw the ecal panel.
- ecalPanel.redraw();
- }
-
- /**
* <b>resize</b><br/><br/>
* <code>private void <b>resize</b>()</code><br/><br/>
* Handles proper resizing of the window and its components.
**/
private void resize() {
- // Size and position the calorimeter display
+ // Define the status panel height.
+ int statusHeight = 125;
+
+ // Size and position the calorimeter display.
ecalPanel.setLocation(0, 0);
- ecalPanel.setSize(getContentPane().getSize());
+ ecalPanel.setSize(getContentPane().getWidth(), getContentPane().getHeight() - statusHeight);
+
+ // Size and position the status panel.
+ statusPanel.setLocation(0, ecalPanel.getHeight());
+ statusPanel.setSize(getContentPane().getWidth(), statusHeight);
}
/**
* <b>getPanelX</b><br/><br/>
- * <code>private int <b>getPanelX</b>(int ecalX)</code><br/><br/>
- * Converts the lcsim x-coordinate to the calorimeter panel's coordinate
+ * <code>public int <b>getPanelX</b>(int ecalX)</code><br/><br/>
+ * Converts the LCSim x-coordinate to the calorimeter panel's coordinate
* system.
- * @param ecalX - An lcsim calorimeter x-coordinate.
+ * @param ecalX - An LCSim calorimeter x-coordinate.
* @return Returns the x-coordinate in the calorimeter panel's coordinate
* system as an <code>int</code>.
**/
- private int getPanelX(int ecalX) {
- if (ecalX <= 0) {
- return ecalX + 23;
- } else {
- return ecalX + 22;
- }
+ public int getPanelX(int ecalX) {
+ if (ecalX <= 0) { return ecalX + 23; }
+ else { return ecalX + 22; }
}
/**
* <b>getPanelY</b><br/><br/>
- * <code>private int <b>getPanelY</b>(int ecalY)</code><br/><br/>
- * Converts the lcsim y-coordinate to the calorimeter panel's coordinate
+ * <code>public int <b>getPanelY</b>(int ecalY)</code><br/><br/>
+ * Converts the LCSim y-coordinate to the calorimeter panel's coordinate
* system.
- * @param ecalY - An lcsim calorimeter y-coordinate.
+ * @param ecalY - An LCSim calorimeter y-coordinate.
* @return Returns the y-coordinate in the calorimeter panel's coordinate
* system as an <code>int</code>.
**/
- private int getPanelY(int ecalY) {
- return 5 - ecalY;
+ public int getPanelY(int ecalY) { return 5 - ecalY; }
+
+ /**
+ * <b>getEcalX</b><br/><br/>
+ * <code>public int <b>getEcalX</b>(int panelX)</code><br/><br/>
+ * Converts the panel x-coordinate to the calorimeter's coordinate
+ * system.
+ * @param panelX - A panel x-coordinate.
+ * @return Returns the x-coordinate in the calorimeter's coordinate
+ * system as an <code>int</code>.
+ */
+ public int getEcalX(int panelX) {
+ if(panelX > 22) { return panelX - 22; }
+ else { return panelX - 23; }
}
/**
+ * <b>getEcalY</b><br/><br/>
+ * <code>public int <b>getEcalY</b>(int panelY)</code><br/><br/>
+ * Converts the panel y-coordinate to the calorimeter's coordinate
+ * system.
+ * @param panelY - A panel y-coordinate.
+ * @return Returns the y-coordinate in the calorimeter's coordinate
+ * system as an <code>int</code>.
+ */
+ public int getEcalY(int panelY) { return 5 - panelY; }
+
+ /**
+ * <b>resetCursor</b><br/><br/>
+ * <code>private void <b>resetCursor</b>()</code><br/><br/>
+ * Performs the cursor highlight calculations for whatever the
+ * most recently highlighted crystal was. This should be called
+ * if the panel is cleared to reset the cursor highlight.
+ */
+ private void resetCursor() {
+ Point temp = lastCrystal;
+ lastCrystal = null;
+ setCursorHighlight(temp);
+ }
+
+ /**
+ * <b>setCursorHighlight</b><br/><br/>
+ * <code>private boolean <b>setCursorHighlight</b>(Point crystal)</code><br/><br/>
+ * Sets the highlighting for the indicated crystal and clears the
+ * highlighting on any previously highlighted crystal. Note that
+ * this will clear any existing highlighting.
+ * @param crystal - The crystal to highlight.
+ * @return Returns <code>true</code> if a different crystal is
+ * highlighted than before and <code>false</code> if it is the
+ * same crystal.
+ */
+ private boolean setCursorHighlight(Point crystal) {
+ // Get the appropriate highlight color.
+ Color hc = null;
+ if(!background) { hc = HIGHLIGHT_CURSOR_DARK; }
+ else { hc = HIGHLIGHT_CURSOR_LIGHT; }
+
+ // Define helper variables.
+ boolean crystalChanged;
+ boolean cNull = (crystal == null);
+ boolean lNull = (lastCrystal == null);
+
+ // Determine if the selected crystal has changed.
+ if(cNull && lNull) { crystalChanged = false; }
+ else if(cNull ^ lNull) { crystalChanged = true; }
+ else { crystalChanged = !lastCrystal.equals(crystal); }
+
+ // If so, clear the highlighting and reset it.
+ if(crystalChanged) {
+ // Clear the old highlighting.
+ ecalPanel.clearHighlight();
+
+ // If the current crystal is a cluster, highlight the cluster.
+ Cluster cluster = clusterMap.get(crystal);
+ if(highlight && cluster != null) {
+ for(Point ch : cluster.getComponentHits()) {
+ ecalPanel.setCrystalHighlight(getPanelX(ch.x), getPanelY(ch.y), HIGHLIGHT_CLUSTER_COMPONENT);
+ }
+ for(Point sh : cluster.getSharedHits()) {
+ ecalPanel.setCrystalHighlight(getPanelX(sh.x), getPanelY(sh.y), HIGHLIGHT_CLUSTER_SHARED);
+ }
+ }
+
+ // If the current crystal is defined, highlight it.
+ if(highlight && crystal != null) { ecalPanel.setCrystalHighlight(crystal.x, crystal.y, hc); }
+ }
+
+ // Set the last crystal to match the current one.
+ lastCrystal = crystal;
+
+ // Return whether a redraw is necessary.
+ return crystalChanged;
+ }
+
+ /**
* The <code>EcalListener</code> class binds the enter key to the
- * <code>displayNextEvent</code> method.
+ * <code>displayNextEvent</code> method. Also allows for toggling
+ * of highlighting with 'h' and background with 'b.' Swaps scale
+ * from linear to logarithmic with 'l'.
**/
- private class EcalListener implements KeyListener {
- public void keyPressed(KeyEvent e) {
- }
+ private class EcalKeyListener implements KeyListener {
+ public void keyPressed(KeyEvent e) { }
public void keyReleased(KeyEvent e) {
// If enter was pressed, go to the next event.
if (e.getKeyCode() == 10) {
- try {
- displayNextEvent();
- } catch (IOException ex) {
+ try { displayNextEvent(); }
+ catch (IOException ex) {
System.err.println(ex.getMessage());
System.exit(1);
}
}
+ // 'b' toggles the default white background.
+ else if(e.getKeyCode() == 66) {
+ if(background) { ecalPanel.setCrystalDefaultColor(null); }
+ else { ecalPanel.setCrystalDefaultColor(Color.WHITE); }
+ ecalPanel.redraw();
+ background = !background;
+ }
+ // 'h' toggles highlighting the crystal under the cursor.
+ else if(e.getKeyCode() == 72) {
+ if(highlight) {
+ if(setCursorHighlight(null)) { ecalPanel.redraw(); }
+ }
+ highlight = !highlight;
+ }
+ // 'l' toggles linear or logarithmic scaling.
+ else if(e.getKeyCode() == 76) {
+ if(ecalPanel.isScalingLinear()) { ecalPanel.setScalingLogarithmic(); }
+ else { ecalPanel.setScalingLinear(); }
+ ecalPanel.redraw();
+ }
+ else { System.out.printf("Key Code: %d%n", e.getKeyCode()); }
}
- public void keyTyped(KeyEvent e) {
- }
+ public void keyTyped(KeyEvent e) { }
}
/**
+ * The <code>EcalMouseListener</code> handles removing highlighting
+ * and crystal field information when the cursor leaves the window.
+ */
+ private class EcalMouseListener implements MouseListener {
+ public void mouseClicked(MouseEvent e) { }
+
+ public void mouseEntered(MouseEvent e) { }
+
+ public void mouseExited(MouseEvent e) {
+ setCursorHighlight(null);
+ statusPanel.clearValues();
+ ecalPanel.redraw();
+ }
+
+ public void mousePressed(MouseEvent e) { }
+
+ public void mouseReleased(MouseEvent e) { }
+ }
+
+ /**
+ * The <code>EcalMouseMotionListener</code> handles updating of
+ * the highlighted crystal and status panel information when the
+ * mouse moves over the window.
+ */
+ private class EcalMouseMotionListener implements MouseMotionListener {
+ public void mouseDragged(MouseEvent arg0) { }
+
+ public void mouseMoved(MouseEvent e) {
+ // Get the mouse coordinates, corrected for the panel position.
+ int correctedX = e.getX();
+ int correctedY = e.getY();
+
+ // Get the crystal that the mouse is in.
+ Point crystal = ecalPanel.getCrystalID(correctedX, correctedY);
+
+ // Mark the current crystal for highlighting.
+ boolean redraw = setCursorHighlight(crystal);
+
+ // If this necessitates a redraw of the panel, do so.
+ if(redraw) {
+ lastCrystal = crystal;
+ ecalPanel.redraw();
+
+ if(crystal != null) {
+ // Determine if the crystal is in the beam gap.
+ boolean[] beamGap = new boolean[2];
+ beamGap[0] = (getEcalY(crystal.y) == 0);
+ beamGap[1] = Math.abs(getEcalY(crystal.y)) == 1 &&
+ (getEcalX(crystal.x) >= -10 && getEcalX(crystal.x) <= -2);
+
+ if(beamGap[0] || beamGap[1]) { statusPanel.clearValues(); }
+ else {
+ statusPanel.setFieldValue(0, String.valueOf(getEcalX(crystal.x)));
+ statusPanel.setFieldValue(1, String.valueOf(getEcalY(crystal.y)));
+ DecimalFormat formatter = new DecimalFormat("0.####E0");
+ String energy = formatter.format(ecalPanel.getCrystalEnergy(crystal.x, crystal.y));
+ statusPanel.setFieldValue(2, energy);
+ }
+ }
+ else { statusPanel.clearValues(); }
+ }
+ }
+ }
+
+ /**
* The <code>ResizeListener</code> class ensures that the components remain
* at the correct size and location when the window is resized.
**/
SVNspam 0.1