Author: mccaky
Date: Sat Nov 1 02:29:56 2014
New Revision: 1384
Log:
Added updated event display GUI and ability to display ecal hardware settings on status panel.
Added:
java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/DataFileViewer.java (with props)
java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/PDataEventViewer.java (with props)
java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/ResizableFieldPanel.java (with props)
java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/util/CrystalDataSet.java (with props)
java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/util/EcalWiringManager.java (with props)
Modified:
java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/ActiveViewer.java
java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/ClusterViewer.java
java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/FileViewer.java
java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/OccupancyViewer.java
java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/PEventViewer.java
java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/POccupancyViewer.java
java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/PassiveViewer.java
java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/StatusPanel.java
java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/Viewer.java
Modified: java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/ActiveViewer.java
=============================================================================
--- java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/ActiveViewer.java (original)
+++ java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/ActiveViewer.java Sat Nov 1 02:29:56 2014
@@ -19,50 +19,43 @@
* @author Kyle McCarty
*/
public abstract class ActiveViewer extends Viewer {
- private static final long serialVersionUID = -6107646224627009923L;
- // Stores whether the background color is set or not.
- private boolean background = false;
- // Gets events from some file.
- protected final EventManager em;
-
- /**
- * Creates an active-type <code>Viewer</code> window which draws
- * events from the indicated data source.
- * @param em - The data source event manager.
- */
- public ActiveViewer(EventManager em) { this(em, new String[0]); }
-
- /**
+ private static final long serialVersionUID = -6107646224627009923L;
+ // Stores whether the background color is set or not.
+ private boolean background = false;
+ // Gets events from some file.
+ protected final EventManager em;
+
+ /**
* Creates an active-type <code>Viewer</code> window which draws
* events from the indicated data source with additional status
* fields defined by the <code>fieldNames</code> argument.
- * @param em - The data source event manager.
- * @param fieldNames - An array of additional status fields
- * that should be displayed.
- */
- public ActiveViewer(EventManager em, String... fieldNames) {
- // Pass any additional field values to the super class.
- super(fieldNames);
-
- // Set the data source.
- this.em = em;
-
+ * @param em - The data source event manager.
+ * @param fieldNames - An array of additional status fields
+ * that should be displayed.
+ */
+ public ActiveViewer(EventManager em) {
+ // Pass any additional field values to the super class.
+ super();
+
+ // Set the data source.
+ this.em = em;
+
// Make a key listener to change events.
addKeyListener(new EcalKeyListener());
- }
-
+ }
+
/**
* Feeds the calorimeter panel the data from the next event.
* @throws IOException Occurs when there is an issue with reading the data file.
**/
- public abstract void displayNextEvent() throws IOException;
-
+ public abstract void displayNextEvent() throws IOException;
+
/**
* Feeds the calorimeter panel the data from the previous event.
* @throws IOException Occurs when there is an issue with reading the data file.
**/
- public abstract void displayPreviousEvent() throws IOException;
-
+ public abstract void displayPreviousEvent() throws IOException;
+
/**
* The <code>EcalListener</code> class binds keys to actions.
* Bound actions include:
@@ -71,7 +64,7 @@
* b :: Toggle color-mapping for 0 energy crystals
* h :: Toggle selected crystal highlighting
* l :: Toggle logarithmic versus linear scaling
- * s :: Saves the current display to a file
+ * s :: Saves the current display to a file
**/
private class EcalKeyListener implements KeyListener {
public void keyPressed(KeyEvent e) { }
@@ -97,9 +90,9 @@
// 'b' toggles the default white background.
else if(e.getKeyCode() == 66) {
- if(background) { ecalPanel.setDefaultCrystalColor(null); }
- else { ecalPanel.setDefaultCrystalColor(Color.GRAY); }
- background = !background;
+ if(background) { ecalPanel.setDefaultCrystalColor(null); }
+ else { ecalPanel.setDefaultCrystalColor(Color.GRAY); }
+ background = !background;
}
// 'h' toggles highlighting the crystal under the cursor.
@@ -107,45 +100,45 @@
// 'l' toggles linear or logarithmic scaling.
else if(e.getKeyCode() == 76) {
- if(ecalPanel.isScalingLinear()) { ecalPanel.setScalingLogarithmic(); }
- else { ecalPanel.setScalingLinear(); }
+ if(ecalPanel.isScalingLinear()) { ecalPanel.setScalingLogarithmic(); }
+ else { ecalPanel.setScalingLinear(); }
}
// 'x' toggles x-axis mirroring.
else if(e.getKeyCode() == 88) {
- ecalPanel.setMirrorX(!ecalPanel.isMirroredX());
- updateStatusPanel();
+ ecalPanel.setMirrorX(!ecalPanel.isMirroredX());
+ updateStatusPanel();
}
// 'y' toggles y-axis mirroring.
else if(e.getKeyCode() == 89) {
- ecalPanel.setMirrorY(!ecalPanel.isMirroredY());
- updateStatusPanel();
+ ecalPanel.setMirrorY(!ecalPanel.isMirroredY());
+ updateStatusPanel();
}
// 's' saves the panel to a file.
else if(e.getKeyCode() == 83) {
- // Make a new buffered image on which to draw the content pane.
- BufferedImage screenshot = new BufferedImage(getContentPane().getWidth(),
- getContentPane().getHeight(), BufferedImage.TYPE_INT_ARGB);
-
- // Paint the content pane to image.
- getContentPane().paint(screenshot.getGraphics());
-
- // Get the lowest available file name.
- int fileNum = 0;
- File imageFile = new File("screenshot_" + fileNum + ".png");
- while(imageFile.exists()) {
- fileNum++;
- imageFile = new File("screenshot_" + fileNum + ".png");
- }
-
- // Save the image to a PNG file.
- try { ImageIO.write(screenshot, "PNG", imageFile); }
- catch(IOException ioe) {
- System.err.println("Error saving file \"screenshot.png\".");
- }
- System.out.println("Screenshot saved to: " + imageFile.getAbsolutePath());
+ // Make a new buffered image on which to draw the content pane.
+ BufferedImage screenshot = new BufferedImage(getContentPane().getWidth(),
+ getContentPane().getHeight(), BufferedImage.TYPE_INT_ARGB);
+
+ // Paint the content pane to image.
+ getContentPane().paint(screenshot.getGraphics());
+
+ // Get the lowest available file name.
+ int fileNum = 0;
+ File imageFile = new File("screenshot_" + fileNum + ".png");
+ while(imageFile.exists()) {
+ fileNum++;
+ imageFile = new File("screenshot_" + fileNum + ".png");
+ }
+
+ // Save the image to a PNG file.
+ try { ImageIO.write(screenshot, "PNG", imageFile); }
+ catch(IOException ioe) {
+ System.err.println("Error saving file \"screenshot.png\".");
+ }
+ System.out.println("Screenshot saved to: " + imageFile.getAbsolutePath());
}
// Otherwise, print out the key code for the pressed key.
Modified: java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/ClusterViewer.java
=============================================================================
--- java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/ClusterViewer.java (original)
+++ java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/ClusterViewer.java Sat Nov 1 02:29:56 2014
@@ -31,10 +31,11 @@
*
* @author Kyle McCarty
*/
+@Deprecated
public class ClusterViewer extends ActiveViewer {
- private static final long serialVersionUID = 17058336873349781L;
- // Stores whether the background color is set or not.
- private boolean background = false;
+ private static final long serialVersionUID = 17058336873349781L;
+ // Stores whether the background color is set or not.
+ private boolean background = false;
// Store the index in the buffer of the displayed event.
private int bufferIndex;
// Map cluster location to a cluster object.
@@ -50,197 +51,205 @@
// Additional status display field names for this data type.
private static final String[] fieldNames = { "Shared Hits", "Component Hits", "Cluster Energy", "Buffer Index" };
- /**
- * <b>ClusterViewer</b><br/><br/>
+ /**
+ * <b>ClusterViewer</b><br/><br/>
* <code>public <b>ClusterViewer</b>()</code><br/><br/>
* Constructs a new <code>Viewer</code> for displaying data read
* from a file.
- * @param dataSource - The <code>EventManager</code> responsible
- * for reading data from a file.
- * @throws NullPointerException Occurs if the event manager is
- * <code>null</code>.
- */
- public ClusterViewer(EventManager dataSource, int eventWindow) throws NullPointerException {
- // Pass any additional fields required by the event manager
- // to the underlying Viewer object to be added to the status
- // display panel.
- super(dataSource, fieldNames);
-
- // Define the event window and initialize the event data.
- this.eventWindow = eventWindow;
- eventEnergyBuffer = new LinkedList<Double[][]>();
- eventHitBuffer = new LinkedList<List<EcalHit>>();
-
- // Prepare the event buffer to display the first event.
- try {
- // Make an empty array. At the start, there are no previous
- // events to load.
- Double[][] emptyArray = new Double[46][11];
- for(int x = 0; x < 46; x++) {
- for(int y = 0; y < 11; y++) { emptyArray[x][y] = new Double(0.0); }
- }
-
- // Populate the eventWindow before section of the buffer
- // with the empty events.
- for(int i = 0; i <= eventWindow; i++) {
- eventEnergyBuffer.addFirst(emptyArray);
- eventHitBuffer.addFirst(new ArrayList<EcalHit>());
- }
-
- // Fill the rest of the array with future events.
- for(int i = 0; i < eventWindow; i++) {
- em.nextEvent();
- eventEnergyBuffer.addFirst(toEnergyArray(em.getHits()));
- eventHitBuffer.addFirst(em.getHits());
- }
- }
- catch(java.io.IOException e) { System.exit(1); }
-
+ * @param dataSource - The <code>EventManager</code> responsible
+ * for reading data from a file.
+ * @throws NullPointerException Occurs if the event manager is
+ * <code>null</code>.
+ */
+ public ClusterViewer(EventManager dataSource, int eventWindow) throws NullPointerException {
+ // Initialize the superclass.
+ super(dataSource);
+
+ // Add the additional fields.
+ for(String field : fieldNames) {
+ addStatusField(field);
+ }
+
+ // Define the event window and initialize the event data.
+ this.eventWindow = eventWindow;
+ eventEnergyBuffer = new LinkedList<Double[][]>();
+ eventHitBuffer = new LinkedList<List<EcalHit>>();
+
+ // Prepare the event buffer to display the first event.
+ try {
+ // Make an empty array. At the start, there are no previous
+ // events to load.
+ Double[][] emptyArray = new Double[46][11];
+ for(int x = 0; x < 46; x++) {
+ for(int y = 0; y < 11; y++) { emptyArray[x][y] = new Double(0.0); }
+ }
+
+ // Populate the eventWindow before section of the buffer
+ // with the empty events.
+ for(int i = 0; i <= eventWindow; i++) {
+ eventEnergyBuffer.addFirst(emptyArray);
+ eventHitBuffer.addFirst(new ArrayList<EcalHit>());
+ }
+
+ // Fill the rest of the array with future events.
+ for(int i = 0; i < eventWindow; i++) {
+ em.nextEvent();
+ eventEnergyBuffer.addFirst(toEnergyArray(em.getHits()));
+ eventHitBuffer.addFirst(em.getHits());
+ }
+ }
+ catch(java.io.IOException e) { System.exit(1); }
+
// Make a key listener to change events.
addKeyListener(new EcalKeyListener());
- }
-
- /**
- * <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.
**/
+ @Override
public void displayNextEvent() throws IOException { getEvent(true); }
/**
- * <b>displayPreviousEvent</b><br/><br/>
- * <code>public void <b>displayPreviousEvent</b>()</code><br/><br/>
* Feeds the calorimeter panel the data from the previous event.
* @throws IOException Occurs when there is an issue with reading the data file.
**/
+ @Override
public void displayPreviousEvent() throws IOException { getEvent(false); }
-
- public List<Cluster> getClusters() {
- // Get the set of hits in the middle of the buffer. This is
- // the "current" event.
- List<EcalHit> activeEvent = eventHitBuffer.get(eventWindow);
-
- // Store clusters.
- ArrayList<Cluster> clusterList = new ArrayList<Cluster>();
-
- // For each hit, check if it meets the criteria for a cluster.
- for(EcalHit hit : activeEvent) {
- // Track whether this hit is a cluster.
- boolean isCluster = true;
-
- // Track the current hit's cluster energy.
- double clusterEnergy = 0.0;
-
- // Convert the current hit to the proper coordinates.
- Point hitLoc = toPanelPoint(hit.getLocation());
-
- // Track which crystals are part of the cluster.
- HashSet<Point> componentSet = new HashSet<Point>();
-
- // Get the set of the current hit's neighbors.
- Set<Point> neighbors = ecalPanel.getNeighbors(hitLoc);
-
- // Loop through the buffer and perform comparisons.
- for(Double[][] event : eventEnergyBuffer) {
- // Increment the cluster energy by the hit's energy at
- // the current time in the buffer.
- clusterEnergy += event[hitLoc.x][hitLoc.y];
-
- // A hit must be larger than itself at all other times
- // stored in the buffer.
- if(event[hitLoc.x][hitLoc.y] > hit.getEnergy()) {
- isCluster = false;
- break;
- }
-
- // A hit must be larger than its immediate neighbors
- // at all times in the buffer as well.
- for(Point neighbor : neighbors) {
- // Increment the cluster energy by the neighbor's
- // energy at the current time in the buffer.
- clusterEnergy += event[neighbor.x][neighbor.y];
-
- // Check that the neighbor's energy is not higher
- // than the present hit's.
- if(event[neighbor.x][neighbor.y] > hit.getEnergy()) {
- isCluster = false;
- break;
- }
-
- // If this neighbor has a non-zero energy, it is
- // a component of the potential cluster.
- if(event[neighbor.x][neighbor.y] != 0) { componentSet.add(neighbor); }
- }
- }
-
- // If the current hit did not fail any of the preceding
- // checks, then it is a cluster and should be added to
- // the cluster list.
- if(isCluster) {
- Cluster cluster = new Cluster(hit.getLocation(), clusterEnergy);
- for(Point neighbor : componentSet) { cluster.addComponentHit(toEcalPoint(neighbor)); }
- clusterList.add(cluster);
- }
- }
-
- // Return the list of clusters.
- return clusterList;
- }
-
+
+ /**
+ * Generates a list of clusters from the list of hits in the event.
+ * This was used as a debugging method for the current clustering
+ * algorithm.
+ * @return Returns a generated list of clusters.
+ */
+ public List<Cluster> getClusters() {
+ // Get the set of hits in the middle of the buffer. This is
+ // the "current" event.
+ List<EcalHit> activeEvent = eventHitBuffer.get(eventWindow);
+
+ // Store clusters.
+ ArrayList<Cluster> clusterList = new ArrayList<Cluster>();
+
+ // For each hit, check if it meets the criteria for a cluster.
+ for(EcalHit hit : activeEvent) {
+ // Track whether this hit is a cluster.
+ boolean isCluster = true;
+
+ // Track the current hit's cluster energy.
+ double clusterEnergy = 0.0;
+
+ // Convert the current hit to the proper coordinates.
+ Point hitLoc = toPanelPoint(hit.getLocation());
+
+ // Track which crystals are part of the cluster.
+ HashSet<Point> componentSet = new HashSet<Point>();
+
+ // Get the set of the current hit's neighbors.
+ Set<Point> neighbors = ecalPanel.getNeighbors(hitLoc);
+
+ // Loop through the buffer and perform comparisons.
+ for(Double[][] event : eventEnergyBuffer) {
+ // Increment the cluster energy by the hit's energy at
+ // the current time in the buffer.
+ clusterEnergy += event[hitLoc.x][hitLoc.y];
+
+ // A hit must be larger than itself at all other times
+ // stored in the buffer.
+ if(event[hitLoc.x][hitLoc.y] > hit.getEnergy()) {
+ isCluster = false;
+ break;
+ }
+
+ // A hit must be larger than its immediate neighbors
+ // at all times in the buffer as well.
+ for(Point neighbor : neighbors) {
+ // Increment the cluster energy by the neighbor's
+ // energy at the current time in the buffer.
+ clusterEnergy += event[neighbor.x][neighbor.y];
+
+ // Check that the neighbor's energy is not higher
+ // than the present hit's.
+ if(event[neighbor.x][neighbor.y] > hit.getEnergy()) {
+ isCluster = false;
+ break;
+ }
+
+ // If this neighbor has a non-zero energy, it is
+ // a component of the potential cluster.
+ if(event[neighbor.x][neighbor.y] != 0) { componentSet.add(neighbor); }
+ }
+ }
+
+ // If the current hit did not fail any of the preceding
+ // checks, then it is a cluster and should be added to
+ // the cluster list.
+ if(isCluster) {
+ Cluster cluster = new Cluster(hit.getLocation(), clusterEnergy);
+ for(Point neighbor : componentSet) { cluster.addComponentHit(toEcalPoint(neighbor)); }
+ clusterList.add(cluster);
+ }
+ }
+
+ // Return the list of clusters.
+ return clusterList;
+ }
+
+ @Override
protected void updateStatusPanel() {
- super.updateStatusPanel();
-
- // Get the currently selected crystal.
- Point crystal = ecalPanel.getSelectedCrystal();
-
- // If the active crystal is not null, see if it is a cluster.
- if(crystal != null) {
- // Get the cluster associated with this point.
- Cluster activeCluster = clusterMap.get(crystal);
-
- // If the cluster is null, we set everything to undefined.
- if(activeCluster == null) {
- for(String field : fieldNames) { setStatusField(field, StatusPanel.NULL_VALUE); }
- }
-
- // Otherwise, define the fields based on the cluster.
- else {
- // Get the shared and component hit counts.
- setStatusField(fieldNames[0], Integer.toString(activeCluster.getSharedHitCount()));
- setStatusField(fieldNames[1], Integer.toString(activeCluster.getComponentHitCount()));
-
- // Format the cluster energy, or account for it if it
- // doesn't exist.
- String energy;
- if(activeCluster.getClusterEnergy() != Double.NaN) {
- DecimalFormat formatter = new DecimalFormat("0.####E0");
- energy = formatter.format(activeCluster.getClusterEnergy());
- }
- else { energy = "---"; }
- setStatusField(fieldNames[2], energy);
- }
- }
- // Otherwise, clear the field values.
- else { for(String field : fieldNames) { setStatusField(field, StatusPanel.NULL_VALUE); } }
-
- // Write the current buffer index.
-
- setStatusField(fieldNames[3], Integer.toString(eventWindow - bufferIndex));
- }
-
- /**
- * <b>displayEvent</b><br/><br/>
- * <code>private void <b>displayEvent</b></code><br/><br/>
- * Displays the given lists of hits and clusters on the calorimeter
- * panel.
- * @param hitList - A list of hits for the current event.
- * @param clusterList - A list of clusters for the current event.
- */
- private void displayEvent(List<EcalHit> hitList, List<Cluster> clusterList) {
- // Suppress the calorimeter panel.
- ecalPanel.setSuppressRedraw(true);
-
+ super.updateStatusPanel();
+
+ // Get the currently selected crystal.
+ Point crystal = ecalPanel.getSelectedCrystal();
+
+ // If the active crystal is not null, see if it is a cluster.
+ if(crystal != null) {
+ // Get the cluster associated with this point.
+ Cluster activeCluster = clusterMap.get(crystal);
+
+ // If the cluster is null, we set everything to undefined.
+ if(activeCluster == null) {
+ for(String field : fieldNames) { setStatusField(field, StatusPanel.NULL_VALUE); }
+ }
+
+ // Otherwise, define the fields based on the cluster.
+ else {
+ // Get the shared and component hit counts.
+ setStatusField(fieldNames[0], Integer.toString(activeCluster.getSharedHitCount()));
+ setStatusField(fieldNames[1], Integer.toString(activeCluster.getComponentHitCount()));
+
+ // Format the cluster energy, or account for it if it
+ // doesn't exist.
+ String energy;
+ if(activeCluster.getClusterEnergy() != Double.NaN) {
+ DecimalFormat formatter = new DecimalFormat("0.####E0");
+ energy = formatter.format(activeCluster.getClusterEnergy());
+ }
+ else { energy = "---"; }
+ setStatusField(fieldNames[2], energy);
+ }
+ }
+ // Otherwise, clear the field values.
+ else { for(String field : fieldNames) { setStatusField(field, StatusPanel.NULL_VALUE); } }
+
+ // Write the current buffer index.
+
+ setStatusField(fieldNames[3], Integer.toString(eventWindow - bufferIndex));
+ }
+
+ /**
+ * <b>displayEvent</b><br/><br/>
+ * <code>private void <b>displayEvent</b></code><br/><br/>
+ * Displays the given lists of hits and clusters on the calorimeter
+ * panel.
+ * @param hitList - A list of hits for the current event.
+ * @param clusterList - A list of clusters for the current event.
+ */
+ private void displayEvent(List<EcalHit> hitList, List<Cluster> clusterList) {
+ // Suppress the calorimeter panel.
+ ecalPanel.setSuppressRedraw(true);
+
// Display the hits.
for (EcalHit h : hitList) {
int ix = toPanelX(h.getX());
@@ -250,28 +259,28 @@
// Display the clusters.
for(Cluster cluster : clusterList) {
- Point rawCluster = cluster.getClusterCenter();
- Point clusterCenter = toPanelPoint(rawCluster);
+ Point rawCluster = cluster.getClusterCenter();
+ Point clusterCenter = toPanelPoint(rawCluster);
ecalPanel.setCrystalCluster(clusterCenter.x, clusterCenter.y, true);
- // Add component hits to the calorimeter panel.
- for(Point ch : cluster.getComponentHits()) {
- ecalPanel.addAssociation(new Association(clusterCenter, toPanelPoint(ch), HIGHLIGHT_CLUSTER_COMPONENT));
- }
-
- // Add shared hits to the calorimeter panel.
- for(Point sh : cluster.getSharedHits()) {
- ecalPanel.addAssociation(new Association(clusterCenter, toPanelPoint(sh), HIGHLIGHT_CLUSTER_SHARED));
- }
- }
-
- // Stop suppressing the panel and order it to redraw.
- ecalPanel.setSuppressRedraw(false);
- ecalPanel.repaint();
+ // Add component hits to the calorimeter panel.
+ for(Point ch : cluster.getComponentHits()) {
+ ecalPanel.addAssociation(new Association(clusterCenter, toPanelPoint(ch), HIGHLIGHT_CLUSTER_COMPONENT));
+ }
+
+ // Add shared hits to the calorimeter panel.
+ for(Point sh : cluster.getSharedHits()) {
+ ecalPanel.addAssociation(new Association(clusterCenter, toPanelPoint(sh), HIGHLIGHT_CLUSTER_SHARED));
+ }
+ }
+
+ // Stop suppressing the panel and order it to redraw.
+ ecalPanel.setSuppressRedraw(false);
+ ecalPanel.repaint();
// Update the status panel to account for the new event.
updateStatusPanel();
- }
+ }
/**
* <b>getEvent</b><br/><br/>
@@ -294,16 +303,16 @@
// Remove the last buffer event and add the new one.
if(forward) {
- eventEnergyBuffer.removeLast();
- eventHitBuffer.removeLast();
- eventEnergyBuffer.addFirst(toEnergyArray(em.getHits()));
- eventHitBuffer.addFirst(em.getHits());
+ eventEnergyBuffer.removeLast();
+ eventHitBuffer.removeLast();
+ eventEnergyBuffer.addFirst(toEnergyArray(em.getHits()));
+ eventHitBuffer.addFirst(em.getHits());
}
else {
- eventEnergyBuffer.removeFirst();
- eventHitBuffer.removeFirst();
- eventEnergyBuffer.addLast(toEnergyArray(em.getHits()));
- eventHitBuffer.addLast(em.getHits());
+ eventEnergyBuffer.removeFirst();
+ eventHitBuffer.removeFirst();
+ eventEnergyBuffer.addLast(toEnergyArray(em.getHits()));
+ eventHitBuffer.addLast(em.getHits());
}
// Determine if any of the hits in the active event are
@@ -321,29 +330,36 @@
// Display it.
displayEvent(eventHitBuffer.get(eventWindow), eventClusters);
}
-
- private Double[][] toEnergyArray(List<EcalHit> hits) {
- // Define the energy array.
- Double[][] energy = new Double[46][11];
- for(int x = 0; x < energy.length; x++) {
- for(int y = 0; y < energy[x].length; y++) {
- energy[x][y] = new Double(0);
- }
- }
-
- // For each hit, place its energy in the array.
- for(EcalHit hit : hits) {
- // Get the converted crystal index.
- Point panelLoc = toPanelPoint(hit.getLocation());
-
- // Add the energy to the array.
- energy[panelLoc.x][panelLoc.y] += hit.getEnergy();
- }
-
- // Return the resulting array.
- return energy;
- }
-
+
+ /**
+ * Gets the energy that should be stored in each crystal of the
+ * calorimeter.
+ * @param hits - The list of hits for the event.
+ * @return Returns the energy of each crystal as an array of <code>
+ * Double</code> objects.
+ */
+ private Double[][] toEnergyArray(List<EcalHit> hits) {
+ // Define the energy array.
+ Double[][] energy = new Double[46][11];
+ for(int x = 0; x < energy.length; x++) {
+ for(int y = 0; y < energy[x].length; y++) {
+ energy[x][y] = new Double(0);
+ }
+ }
+
+ // For each hit, place its energy in the array.
+ for(EcalHit hit : hits) {
+ // Get the converted crystal index.
+ Point panelLoc = toPanelPoint(hit.getLocation());
+
+ // Add the energy to the array.
+ energy[panelLoc.x][panelLoc.y] += hit.getEnergy();
+ }
+
+ // Return the resulting array.
+ return energy;
+ }
+
/**
* The <code>EcalListener</code> class binds keys to actions.
* Bound actions include:
@@ -352,11 +368,13 @@
* b :: Toggle color-mapping for 0 energy crystals
* h :: Toggle selected crystal highlighting
* l :: Toggle logarithmic versus linear scaling
- * s :: Saves the current display to a file
+ * s :: Saves the current display to a file
**/
private class EcalKeyListener implements KeyListener {
+ @Override
public void keyPressed(KeyEvent e) { }
+ @Override
public void keyReleased(KeyEvent e) {
// If right-arrow was pressed, go to the next event.
if (e.getKeyCode() == 39) {
@@ -379,30 +397,30 @@
// If the down-arrow was pressed, move down a time step in
// the buffer and display it.
else if(e.getKeyCode() == 40) {
- if(bufferIndex == eventHitBuffer.size() - 1) { return; }
- else {
- bufferIndex++;
- ecalPanel.clearCrystals();
- displayEvent(eventHitBuffer.get(bufferIndex), eventClusters);
- }
+ if(bufferIndex == eventHitBuffer.size() - 1) { return; }
+ else {
+ bufferIndex++;
+ ecalPanel.clearCrystals();
+ displayEvent(eventHitBuffer.get(bufferIndex), eventClusters);
+ }
}
// If the up-arrow was pressed, move up a time step in
// the buffer and display it.
else if(e.getKeyCode() == 38) {
- if(bufferIndex == 0) { return; }
- else {
- bufferIndex--;
- ecalPanel.clearCrystals();
- displayEvent(eventHitBuffer.get(bufferIndex), eventClusters);
- }
+ if(bufferIndex == 0) { return; }
+ else {
+ bufferIndex--;
+ ecalPanel.clearCrystals();
+ displayEvent(eventHitBuffer.get(bufferIndex), eventClusters);
+ }
}
// 'b' toggles the default white background.
else if(e.getKeyCode() == 66) {
- if(background) { ecalPanel.setDefaultCrystalColor(null); }
- else { ecalPanel.setDefaultCrystalColor(Color.GRAY); }
- background = !background;
+ if(background) { ecalPanel.setDefaultCrystalColor(null); }
+ else { ecalPanel.setDefaultCrystalColor(Color.GRAY); }
+ background = !background;
}
// 'h' toggles highlighting the crystal under the cursor.
@@ -410,39 +428,40 @@
// 'l' toggles linear or logarithmic scaling.
else if(e.getKeyCode() == 76) {
- if(ecalPanel.isScalingLinear()) { ecalPanel.setScalingLogarithmic(); }
- else { ecalPanel.setScalingLinear(); }
+ if(ecalPanel.isScalingLinear()) { ecalPanel.setScalingLogarithmic(); }
+ else { ecalPanel.setScalingLinear(); }
}
// 's' saves the panel to a file.
else if(e.getKeyCode() == 83) {
- // Make a new buffered image on which to draw the content pane.
- BufferedImage screenshot = new BufferedImage(getContentPane().getWidth(),
- getContentPane().getHeight(), BufferedImage.TYPE_INT_ARGB);
-
- // Paint the content pane to image.
- getContentPane().paint(screenshot.getGraphics());
-
- // Get the lowest available file name.
- int fileNum = 0;
- File imageFile = new File("screenshot_" + fileNum + ".png");
- while(imageFile.exists()) {
- fileNum++;
- imageFile = new File("screenshot_" + fileNum + ".png");
- }
-
- // Save the image to a PNG file.
- try { ImageIO.write(screenshot, "PNG", imageFile); }
- catch(IOException ioe) {
- System.err.println("Error saving file \"screenshot.png\".");
- }
- System.out.println("Screenshot saved to: " + imageFile.getAbsolutePath());
+ // Make a new buffered image on which to draw the content pane.
+ BufferedImage screenshot = new BufferedImage(getContentPane().getWidth(),
+ getContentPane().getHeight(), BufferedImage.TYPE_INT_ARGB);
+
+ // Paint the content pane to image.
+ getContentPane().paint(screenshot.getGraphics());
+
+ // Get the lowest available file name.
+ int fileNum = 0;
+ File imageFile = new File("screenshot_" + fileNum + ".png");
+ while(imageFile.exists()) {
+ fileNum++;
+ imageFile = new File("screenshot_" + fileNum + ".png");
+ }
+
+ // Save the image to a PNG file.
+ try { ImageIO.write(screenshot, "PNG", imageFile); }
+ catch(IOException ioe) {
+ System.err.println("Error saving file \"screenshot.png\".");
+ }
+ System.out.println("Screenshot saved to: " + imageFile.getAbsolutePath());
}
// Otherwise, print out the key code for the pressed key.
else { System.out.printf("Key Code: %d%n", e.getKeyCode()); }
}
+ @Override
public void keyTyped(KeyEvent e) { }
}
}
Added: java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/DataFileViewer.java
=============================================================================
--- java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/DataFileViewer.java (added)
+++ java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/DataFileViewer.java Sat Nov 1 02:29:56 2014
@@ -0,0 +1,99 @@
+package org.hps.monitoring.ecal.eventdisplay.ui;
+
+import java.awt.Point;
+import java.io.IOException;
+
+import org.hps.monitoring.ecal.eventdisplay.io.EventManager;
+import org.hps.monitoring.ecal.eventdisplay.util.CrystalDataSet;
+import org.hps.monitoring.ecal.eventdisplay.util.EcalWiringManager;
+
+/**
+ * Class <code>DataFileViewer</code> is the active variant of a data
+ * viewer. It displays crystal hardware information read from a given
+ * data file and displays it along with crystal energy and index data.
+ *
+ * @author Kyle McCarty
+ */
+public class DataFileViewer extends FileViewer {
+ // Local variables.
+ private static final long serialVersionUID = 1L;
+ private final EcalWiringManager ewm;
+
+ // Hardware display fields.
+ private static final String[] fieldNames = {
+ "APD Number", "Preamp Number", "LED Channel", "LED Driver",
+ "FADC Slot", "FADC Channel", "Splitter Number", "HV Group",
+ "Jout", "MB", "Channel", "Gain"
+ };
+
+ // Hardware display field indices.
+ private static final int FIELD_APD = 0;
+ private static final int FIELD_PREAMP = 1;
+ private static final int FIELD_LED_CHANNEL = 2;
+ private static final int FIELD_LED_DRIVER = 3;
+ private static final int FIELD_FADC_SLOT = 4;
+ private static final int FIELD_FADC_CHANNEL = 5;
+ private static final int FIELD_SPLITTER = 6;
+ private static final int FIELD_HV_GROUP = 7;
+ private static final int FIELD_JOUT = 8;
+ private static final int FIELD_MB = 9;
+ private static final int FIELD_CHANNEL = 10;
+ private static final int FIELD_GAIN = 11;
+
+ /**
+ * Initializes a new <code>DataFileViewer</code> that reads from
+ * the given event manager for event data and the given hardware
+ * data file for crystal hardware data readout.
+ * @param dataSource - The manager for event data.
+ * @param crystalDataFilePath - The data file for crystal hardware
+ * information.
+ * @throws IOException Occurs if there is an error reading from
+ * either data source.
+ */
+ public DataFileViewer(EventManager dataSource, String crystalDataFilePath) throws IOException {
+ // Initialize the super class file.
+ super(dataSource);
+
+ // Load the crystal data mapping.
+ ewm = new EcalWiringManager(crystalDataFilePath);
+
+ // Add the crystal data fields.
+ for(String fieldName : fieldNames) {
+ addStatusField(fieldName);
+ }
+ }
+
+ @Override
+ protected void updateStatusPanel() {
+ // Run the superclass method.
+ super.updateStatusPanel();
+
+ // Get the selected crystal.
+ Point crystal = ecalPanel.getSelectedCrystal();
+
+ // If a crystal is selected, display its data set.
+ if(crystal != null) {
+ // Get the LCSim coordinate system version of the crystal.
+ Point lcsimCrystal = Viewer.toEcalPoint(crystal);
+
+ // Get the hardware data set associated with the crystal.
+ CrystalDataSet cds = ewm.getCrystalData(lcsimCrystal);
+
+ // If the data set exists, update the all the fields.
+ if(cds != null) {
+ setStatusField(fieldNames[FIELD_APD], "" + cds.getAPDNumber());
+ setStatusField(fieldNames[FIELD_PREAMP], cds.getPreamplifierNumber().toString());
+ setStatusField(fieldNames[FIELD_LED_CHANNEL], "" + cds.getLEDChannel());
+ setStatusField(fieldNames[FIELD_LED_DRIVER], "" + cds.getLEDDriver());
+ setStatusField(fieldNames[FIELD_FADC_SLOT], "" + cds.getFADCSlot());
+ setStatusField(fieldNames[FIELD_FADC_CHANNEL], "" + cds.getFADCChannel());
+ setStatusField(fieldNames[FIELD_SPLITTER], "" + cds.getSplitterNumber());
+ setStatusField(fieldNames[FIELD_HV_GROUP], "" + cds.getHighVoltageGroup());
+ setStatusField(fieldNames[FIELD_JOUT], "" + cds.getJout());
+ setStatusField(fieldNames[FIELD_MB], "" + cds.getMB());
+ setStatusField(fieldNames[FIELD_CHANNEL], "" + cds.getChannel());
+ setStatusField(fieldNames[FIELD_GAIN], "" + cds.getGain());
+ }
+ }
+ }
+}
Modified: java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/FileViewer.java
=============================================================================
--- java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/FileViewer.java (original)
+++ java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/FileViewer.java Sat Nov 1 02:29:56 2014
@@ -21,7 +21,7 @@
* @author Kyle McCarty
*/
public class FileViewer extends ActiveViewer {
- private static final long serialVersionUID = 17058336873349781L;
+ private static final long serialVersionUID = 17058336873349781L;
// Map cluster location to a cluster object.
private HashMap<Point, Cluster> clusterMap = new HashMap<Point, Cluster>();
// Additional status display field names for this data type.
@@ -32,80 +32,87 @@
private static final int COMPONENT_HITS = 2;
private static final int CLUSTER_ENERGY = 3;
- /**
- * <b>FileViewer</b><br/><br/>
+ /**
+ * <b>FileViewer</b><br/><br/>
* <code>public <b>FileViewer</b>()</code><br/><br/>
* Constructs a new <code>Viewer</code> for displaying data read
* from a file.
- * @param dataSource - The <code>EventManager</code> responsible
- * for reading data from a file.
- * @throws NullPointerException Occurs if the event manager is
- * <code>null</code>.
- */
- public FileViewer(EventManager dataSource) throws NullPointerException {
- // Pass any additional fields required by the event manager
- // to the underlying Viewer object to be added to the status
- // display panel.
- super(dataSource, fieldNames);
- }
+ * @param dataSource - The <code>EventManager</code> responsible
+ * for reading data from a file.
+ * @throws NullPointerException Occurs if the event manager is
+ * <code>null</code>.
+ */
+ public FileViewer(EventManager dataSource) throws NullPointerException {
+ // Initialize the superclass viewer.
+ super(dataSource);
+
+ // Add additional fields.
+ insertStatusField(0, fieldNames[0]);
+ for(int index = 1; index < fieldNames.length; index++) {
+ addStatusField(fieldNames[index]);
+ }
+ }
+ @Override
public void displayNextEvent() throws IOException { getEvent(true); }
+ @Override
public void displayPreviousEvent() throws IOException { getEvent(false); }
+ @Override
protected void updateStatusPanel() {
- // Update the superclass status fields.
- super.updateStatusPanel();
-
- // Get the currently selected crystal.
- Point crystal = ecalPanel.getSelectedCrystal();
-
- // If the active crystal is not null, see if it is a cluster.
- if(crystal != null) {
- // Get the cluster associated with this point.
- Cluster activeCluster = clusterMap.get(crystal);
-
- // If the cluster is null, we set everything to undefined.
- if(activeCluster == null) {
- for(String field : fieldNames) { setStatusField(field, StatusPanel.NULL_VALUE); }
- }
-
- // Otherwise, define the fields based on the cluster.
- else {
- // Get the shared and component hit counts.
- setStatusField(fieldNames[SHARED_HITS], Integer.toString(activeCluster.getSharedHitCount()));
- setStatusField(fieldNames[COMPONENT_HITS], Integer.toString(activeCluster.getComponentHitCount()));
-
- // Format the cluster energy, or account for it if it
- // doesn't exist.
- String energy;
- if(activeCluster.getClusterEnergy() != Double.NaN) {
- DecimalFormat formatter = new DecimalFormat("0.####E0");
- energy = formatter.format(activeCluster.getClusterEnergy());
- }
- else { energy = "---"; }
- setStatusField(fieldNames[CLUSTER_ENERGY], energy);
- }
- }
- // Otherwise, clear the field values.
- else { for(String field : fieldNames) { setStatusField(field, StatusPanel.NULL_VALUE); } }
-
- // Set the event number.
- setStatusField(fieldNames[EVENT_NUMBER], Integer.toString(em.getEventNumber()));
+ // Update the superclass status fields.
+ super.updateStatusPanel();
+
+ // Get the currently selected crystal.
+ Point crystal = ecalPanel.getSelectedCrystal();
+
+ // If the active crystal is not null, see if it is a cluster.
+ if(crystal != null) {
+ // Get the cluster associated with this point.
+ Cluster activeCluster = clusterMap.get(crystal);
+
+ // If the cluster is null, we set everything to undefined.
+ if(activeCluster == null) {
+ for(String field : fieldNames) { setStatusField(field, ResizableFieldPanel.NULL_VALUE); }
+ }
+
+ // Otherwise, define the fields based on the cluster.
+ else {
+ // Get the shared and component hit counts.
+ setStatusField(fieldNames[SHARED_HITS], Integer.toString(activeCluster.getSharedHitCount()));
+ setStatusField(fieldNames[COMPONENT_HITS], Integer.toString(activeCluster.getComponentHitCount()));
+
+ // Format the cluster energy, or account for it if it
+ // doesn't exist.
+ String energy;
+ if(activeCluster.getClusterEnergy() != Double.NaN) {
+ DecimalFormat formatter = new DecimalFormat("0.####E0");
+ energy = formatter.format(activeCluster.getClusterEnergy());
+ }
+ else { energy = "---"; }
+ setStatusField(fieldNames[CLUSTER_ENERGY], energy);
+ }
+ }
+ // Otherwise, clear the field values.
+ else { for(String field : fieldNames) { setStatusField(field, ResizableFieldPanel.NULL_VALUE); } }
+
+ // Set the event number.
+ setStatusField(fieldNames[EVENT_NUMBER], Integer.toString(em.getEventNumber()));
}
- /**
- * <b>displayEvent</b><br/><br/>
- * <code>private void <b>displayEvent</b>(List<EcalHit> hitList, List<Cluster> clusterList)</code><br/><br/>
- * Displays the given lists of hits and clusters on the calorimeter
- * panel.
- * @param hitList - A list of hits for the current event.
- * @param clusterList - A list of clusters for the current event.
- */
- private void displayEvent(List<EcalHit> hitList, List<Cluster> clusterList) {
- // Suppress the calorimeter panel's redrawing.
- ecalPanel.setSuppressRedraw(true);
-
+ /**
+ * <b>displayEvent</b><br/><br/>
+ * <code>private void <b>displayEvent</b>(List<EcalHit> hitList, List<Cluster> clusterList)</code><br/><br/>
+ * Displays the given lists of hits and clusters on the calorimeter
+ * panel.
+ * @param hitList - A list of hits for the current event.
+ * @param clusterList - A list of clusters for the current event.
+ */
+ private void displayEvent(List<EcalHit> hitList, List<Cluster> clusterList) {
+ // Suppress the calorimeter panel's redrawing.
+ ecalPanel.setSuppressRedraw(true);
+
// Display the hits.
for (EcalHit h : hitList) {
int ix = toPanelX(h.getX());
@@ -115,19 +122,19 @@
// Display the clusters.
for(Cluster cluster : clusterList) {
- Point rawCluster = cluster.getClusterCenter();
- Point clusterCenter = toPanelPoint(rawCluster);
+ Point rawCluster = cluster.getClusterCenter();
+ Point clusterCenter = toPanelPoint(rawCluster);
ecalPanel.setCrystalCluster(clusterCenter.x, clusterCenter.y, true);
- // Add component hits to the calorimeter panel.
- for(Point ch : cluster.getComponentHits()) {
- ecalPanel.addAssociation(new Association(clusterCenter, toPanelPoint(ch), HIGHLIGHT_CLUSTER_COMPONENT));
- }
-
- // Add shared hits to the calorimeter panel.
- for(Point sh : cluster.getSharedHits()) {
- ecalPanel.addAssociation(new Association(clusterCenter, toPanelPoint(sh), HIGHLIGHT_CLUSTER_SHARED));
- }
+ // Add component hits to the calorimeter panel.
+ for(Point ch : cluster.getComponentHits()) {
+ ecalPanel.addAssociation(new Association(clusterCenter, toPanelPoint(ch), HIGHLIGHT_CLUSTER_COMPONENT));
+ }
+
+ // Add shared hits to the calorimeter panel.
+ for(Point sh : cluster.getSharedHits()) {
+ ecalPanel.addAssociation(new Association(clusterCenter, toPanelPoint(sh), HIGHLIGHT_CLUSTER_SHARED));
+ }
}
// Stop suppressing the redraw and order the panel to update.
@@ -136,7 +143,7 @@
// Update the status panel to account for the new event.
updateStatusPanel();
- }
+ }
/**
* <b>getEvent</b><br/><br/>
Modified: java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/OccupancyViewer.java
=============================================================================
--- java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/OccupancyViewer.java (original)
+++ java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/OccupancyViewer.java Sat Nov 1 02:29:56 2014
@@ -17,63 +17,59 @@
* @author Kyle McCarty
*/
public class OccupancyViewer extends ActiveViewer {
- private static final long serialVersionUID = 3712604287904215617L;
- // The number of events that have been read so far.
- private long events = 0;
- // The total number of hits for each crystal position.
- private long[][] hits;
-
- /**
- * <b>OccupancyViewer</b><br/><br/>
- * <code>public <b>OccupancyViewer</b>(EventManager em)</code><br/><br/>
+ private static final long serialVersionUID = 3712604287904215617L;
+ // The number of events that have been read so far.
+ private long events = 0;
+ // The total number of hits for each crystal position.
+ private long[][] hits;
+
+ /**
* Creates a new occupancy display that draws event data from the
* indicated data source.
- * @param em - The data source from which to draw events.
- */
- public OccupancyViewer(EventManager em) {
- // Initialize the super class.
- super(em);
-
- // Set the title and scale.
- setTitle("HPS Calorimeter Occupancies");
- ecalPanel.setScaleMaximum(1.0);
-
- // Initialize the hit counts array.
- Dimension ecalSize = ecalPanel.getCrystalBounds();
- hits = new long[ecalSize.width][ecalSize.height];
- }
+ * @param em - The data source from which to draw events.
+ */
+ public OccupancyViewer(EventManager em) {
+ // Initialize the super class.
+ super(em);
+
+ // Set the title and scale.
+ setTitle("HPS Calorimeter Occupancies");
+ ecalPanel.setScaleMaximum(1.0);
+
+ // Initialize the hit counts array.
+ Dimension ecalSize = ecalPanel.getCrystalBounds();
+ hits = new long[ecalSize.width][ecalSize.height];
+ }
+ @Override
public void displayNextEvent() throws IOException { getEvent(true); }
+ @Override
public void displayPreviousEvent() throws IOException { getEvent(false); }
/**
- * <b>resetOccupancies</b><br/><br/>
- * <code>public void <b>resetOccupancies</b>()</code><br/><br/>
* Clears the current occupancy data.
*/
public void resetOccupancies() {
- // Clear the crystal hit counts.
- for(int x = 0; x < hits.length; x++) {
- for(int y = 0; y < hits[0].length; y++) {
- hits[x][y] = 0;
- }
- }
-
- // Clear the number of events.
- events = 0;
+ // Clear the crystal hit counts.
+ for(int x = 0; x < hits.length; x++) {
+ for(int y = 0; y < hits[0].length; y++) {
+ hits[x][y] = 0;
+ }
+ }
+
+ // Clear the number of events.
+ events = 0;
}
- /**
- * <b>displayEvent</b><br/><br/>
- * <code>private void <b>displayEvent</b>(List<EcalHit> hitList)</code><br/><br/>
- * Displays the given lists of hits on the calorimeter panel.
- * @param hitList - A list of hits for the current event.
- */
- private void displayEvent(List<EcalHit> hitList) {
- // Suppress the calorimeter panel's redrawing.
- ecalPanel.setSuppressRedraw(true);
-
+ /**
+ * Displays the given lists of hits on the calorimeter panel.
+ * @param hitList - A list of hits for the current event.
+ */
+ private void displayEvent(List<EcalHit> hitList) {
+ // Suppress the calorimeter panel's redrawing.
+ ecalPanel.setSuppressRedraw(true);
+
// Display the hits.
for (EcalHit h : hitList) {
ecalPanel.addCrystalEnergy(h.getX(), h.getY(), h.getEnergy());
@@ -85,11 +81,9 @@
// Update the status panel to account for the new event.
updateStatusPanel();
- }
+ }
/**
- * <b>getEvent</b><br/><br/>
- * <code>private void <b>getEvent</b>(boolean forward)</code><br/><br/>
* Reads either the next or the previous event from the event manager.
* @param forward - Whether the event data should be read forward
* or backward.
@@ -104,44 +98,44 @@
// Get the next event.
if(forward) {
- // Get the next event.
- em.nextEvent();
-
- // Increment the event count.
- events++;
-
- // For each hit, increment the hit count for the relevant
- // crystal by one.
- for(EcalHit hit : em.getHits()) {
- hits[toPanelX(hit.getX())][toPanelY(hit.getY())]++;
- }
+ // Get the next event.
+ em.nextEvent();
+
+ // Increment the event count.
+ events++;
+
+ // For each hit, increment the hit count for the relevant
+ // crystal by one.
+ for(EcalHit hit : em.getHits()) {
+ hits[toPanelX(hit.getX())][toPanelY(hit.getY())]++;
+ }
}
else {
- // Get the previous event.
- em.previousEvent();
-
- // Decrement the event count.
- events--;
-
- // For each hit, decrement the hit count for the relevant
- // crystal by one.
- for(EcalHit hit : em.getHits()) {
- hits[toPanelX(hit.getX())][toPanelY(hit.getY())]--;
- }
+ // Get the previous event.
+ em.previousEvent();
+
+ // Decrement the event count.
+ events--;
+
+ // For each hit, decrement the hit count for the relevant
+ // crystal by one.
+ for(EcalHit hit : em.getHits()) {
+ hits[toPanelX(hit.getX())][toPanelY(hit.getY())]--;
+ }
}
// Build a "hit list" from the occupancies.
ArrayList<EcalHit> occupancyList = new ArrayList<EcalHit>();
for(int x = 0; x < hits.length; x++) {
- for(int y = 0; y < hits[0].length; y++) {
- if(hits[x][y] != 0) {
- // Define the crystal ID and "energy."
- Point cid = new Point(x, y);
- double occupancy = ((double) hits[x][y]) / events;
- EcalHit occupancyHit = new EcalHit(cid, occupancy);
- occupancyList.add(occupancyHit);
- }
- }
+ for(int y = 0; y < hits[0].length; y++) {
+ if(hits[x][y] != 0) {
+ // Define the crystal ID and "energy."
+ Point cid = new Point(x, y);
+ double occupancy = ((double) hits[x][y]) / events;
+ EcalHit occupancyHit = new EcalHit(cid, occupancy);
+ occupancyList.add(occupancyHit);
+ }
+ }
}
// Display it the occupancies.
Added: java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/PDataEventViewer.java
=============================================================================
--- java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/PDataEventViewer.java (added)
+++ java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/PDataEventViewer.java Sat Nov 1 02:29:56 2014
@@ -0,0 +1,98 @@
+package org.hps.monitoring.ecal.eventdisplay.ui;
+
+import java.awt.Point;
+import java.io.IOException;
+
+import org.hps.monitoring.ecal.eventdisplay.util.CrystalDataSet;
+import org.hps.monitoring.ecal.eventdisplay.util.EcalWiringManager;
+
+/**
+ * Class <code>PDataEventViewer</code> is the passive variant of a data
+ * viewer. It displays crystal hardware information read from a given
+ * data file and displays it along with crystal energy and index data.
+ *
+ * @author Kyle McCarty
+ */
+public class PDataEventViewer extends PEventViewer {
+ // Local variables.
+ private static final long serialVersionUID = 1L;
+ private final EcalWiringManager ewm;
+
+ // Hardware display fields.
+ private static final String[] fieldNames = {
+ "APD Number", "Preamp Number", "LED Channel", "LED Driver",
+ "FADC Slot", "FADC Channel", "Splitter Number", "HV Group",
+ "Jout", "MB", "Channel", "Gain"
+ };
+
+ // Hardware display field indices.
+ private static final int FIELD_APD = 0;
+ private static final int FIELD_PREAMP = 1;
+ private static final int FIELD_LED_CHANNEL = 2;
+ private static final int FIELD_LED_DRIVER = 3;
+ private static final int FIELD_FADC_SLOT = 4;
+ private static final int FIELD_FADC_CHANNEL = 5;
+ private static final int FIELD_SPLITTER = 6;
+ private static final int FIELD_HV_GROUP = 7;
+ private static final int FIELD_JOUT = 8;
+ private static final int FIELD_MB = 9;
+ private static final int FIELD_CHANNEL = 10;
+ private static final int FIELD_GAIN = 11;
+
+ /**
+ * Initializes a new <code>DataFileViewer</code> that reads from
+ * the given event manager for event data and the given hardware
+ * data file for crystal hardware data readout.
+ * @param dataSource - The manager for event data.
+ * @param crystalDataFilePath - The data file for crystal hardware
+ * information.
+ * @throws IOException Occurs if there is an error reading from
+ * either data source.
+ */
+ public PDataEventViewer(String crystalDataFilePath) throws IOException {
+ // Initialize the super class file.
+ super();
+
+ // Load the crystal data mapping.
+ ewm = new EcalWiringManager(crystalDataFilePath);
+
+ // Add the crystal data fields.
+ for(String fieldName : fieldNames) {
+ addStatusField(fieldName);
+ }
+ }
+
+ @Override
+ protected void updateStatusPanel() {
+ // Run the superclass method.
+ super.updateStatusPanel();
+
+ // Get the selected crystal.
+ Point crystal = ecalPanel.getSelectedCrystal();
+
+ // If a crystal is selected, display its data set.
+ if(crystal != null) {
+ // Get the LCSim coordinate system version of the crystal.
+ Point lcsimCrystal = Viewer.toEcalPoint(crystal);
+
+ // Get the hardware data set associated with the crystal.
+ CrystalDataSet cds = ewm.getCrystalData(lcsimCrystal);
+
+ // If the data set exists, update the all the fields.
+ if(cds != null) {
+ setStatusField(fieldNames[FIELD_APD], "" + cds.getAPDNumber());
+ setStatusField(fieldNames[FIELD_PREAMP], cds.getPreamplifierNumber().toString());
+ setStatusField(fieldNames[FIELD_LED_CHANNEL], "" + cds.getLEDChannel());
+ setStatusField(fieldNames[FIELD_LED_DRIVER], "" + cds.getLEDDriver());
+ setStatusField(fieldNames[FIELD_FADC_SLOT], "" + cds.getFADCSlot());
+ setStatusField(fieldNames[FIELD_FADC_CHANNEL], "" + cds.getFADCChannel());
+ setStatusField(fieldNames[FIELD_SPLITTER], "" + cds.getSplitterNumber());
+ setStatusField(fieldNames[FIELD_HV_GROUP], "" + cds.getHighVoltageGroup());
+ setStatusField(fieldNames[FIELD_JOUT], "" + cds.getJout());
+ setStatusField(fieldNames[FIELD_MB], "" + cds.getMB());
+ setStatusField(fieldNames[FIELD_CHANNEL], "" + cds.getChannel());
+ setStatusField(fieldNames[FIELD_GAIN], "" + cds.getGain());
+ }
+ }
+ }
+}
Modified: java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/PEventViewer.java
=============================================================================
--- java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/PEventViewer.java (original)
+++ java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/PEventViewer.java Sat Nov 1 02:29:56 2014
@@ -22,60 +22,58 @@
* @author Kyle McCarty
*/
public class PEventViewer extends PassiveViewer {
- private static final long serialVersionUID = -7479125553259270894L;
- // Stores whether the background color is set or not.
- private boolean background = false;
- // Stores cluster objects.
- protected ArrayList<Cluster> clusterList = new ArrayList<Cluster>();
- // Stores hit objects.
- protected ArrayList<EcalHit> hitList = new ArrayList<EcalHit>();
-
- /**
- * <b>PEventViewer</b><br/><br/>
- * <code>public <b>PEventViewer</b>(String... fieldValues)</code><br/><br/>
- * Creates a passive viewer for displaying hits and clusters in
- * an event.
- * @param fieldValues - Any additional status fields to display.
- */
- public PEventViewer(String... fieldValues) {
- // Pass the field values to the superclass.
- super(fieldValues);
-
- // Set the key bindings.
- addKeyListener(new EcalKeyListener());
- }
-
- public void addHit(EcalHit hit) { hitList.add(hit); }
-
- public void addCluster(Cluster cluster) { clusterList.add(cluster); }
-
- /**
- * <b>clearHits</b><br/><br/>
- * <code>public void <b>clearHits</b>()</code><br/><br/>
- * Removes all of the hit data from the viewer.
- */
- public void clearHits() { hitList.clear(); }
-
- /**
- * <b>clearClusters</b><br/><br/>
- * <code>public void <b>clearClusters</b>()</code><br/><br/>
- * Removes all of the cluster data from the viewer.
- */
- public void clearClusters() { hitList.clear(); }
-
- public void resetDisplay() {
- // Reset the hit and cluster lists.
- hitList.clear();
- clusterList.clear();
- }
-
- public void updateDisplay() {
- // Suppress the calorimeter panel's redrawing.
- ecalPanel.setSuppressRedraw(true);
-
- // Clear the panel data.
- ecalPanel.clearCrystals();
-
+ private static final long serialVersionUID = -7479125553259270894L;
+ // Stores whether the background color is set or not.
+ private boolean background = false;
+ // Stores cluster objects.
+ protected ArrayList<Cluster> clusterList = new ArrayList<Cluster>();
+ // Stores hit objects.
+ protected ArrayList<EcalHit> hitList = new ArrayList<EcalHit>();
+
+ /**
+ * Creates a passive viewer for displaying hits and clusters in
+ * an event.
+ * @param fieldValues - Any additional status fields to display.
+ */
+ public PEventViewer() {
+ // Initialize the superclass.
+ super();
+
+ // Set the key bindings.
+ addKeyListener(new EcalKeyListener());
+ }
+
+ @Override
+ public void addHit(EcalHit hit) { hitList.add(hit); }
+
+ @Override
+ public void addCluster(Cluster cluster) { clusterList.add(cluster); }
+
+ /**
+ * Removes all of the hit data from the viewer.
+ */
+ public void clearHits() { hitList.clear(); }
+
+ /**
+ * Removes all of the cluster data from the viewer.
+ */
+ public void clearClusters() { hitList.clear(); }
+
+ @Override
+ public void resetDisplay() {
+ // Reset the hit and cluster lists.
+ hitList.clear();
+ clusterList.clear();
+ }
+
+ @Override
+ public void updateDisplay() {
+ // Suppress the calorimeter panel's redrawing.
+ ecalPanel.setSuppressRedraw(true);
+
+ // Clear the panel data.
+ ecalPanel.clearCrystals();
+
// Display the hits.
for (EcalHit h : hitList) {
int ix = toPanelX(h.getX());
@@ -85,19 +83,19 @@
// Display the clusters.
for(Cluster cluster : clusterList) {
- Point rawCluster = cluster.getClusterCenter();
- Point clusterCenter = toPanelPoint(rawCluster);
+ Point rawCluster = cluster.getClusterCenter();
+ Point clusterCenter = toPanelPoint(rawCluster);
ecalPanel.setCrystalCluster(clusterCenter.x, clusterCenter.y, true);
- // Add component hits to the calorimeter panel.
- for(Point ch : cluster.getComponentHits()) {
- ecalPanel.addAssociation(new Association(clusterCenter, toPanelPoint(ch), HIGHLIGHT_CLUSTER_COMPONENT));
- }
-
- // Add shared hits to the calorimeter panel.
- for(Point sh : cluster.getSharedHits()) {
- ecalPanel.addAssociation(new Association(clusterCenter, toPanelPoint(sh), HIGHLIGHT_CLUSTER_SHARED));
- }
+ // Add component hits to the calorimeter panel.
+ for(Point ch : cluster.getComponentHits()) {
+ ecalPanel.addAssociation(new Association(clusterCenter, toPanelPoint(ch), HIGHLIGHT_CLUSTER_COMPONENT));
+ }
+
+ // Add shared hits to the calorimeter panel.
+ for(Point sh : cluster.getSharedHits()) {
+ ecalPanel.addAssociation(new Association(clusterCenter, toPanelPoint(sh), HIGHLIGHT_CLUSTER_SHARED));
+ }
}
// Stop suppressing the redraw and order the panel to update.
@@ -106,25 +104,27 @@
// Update the status panel to account for the new event.
updateStatusPanel();
- }
-
+ }
+
/**
* The <code>EcalListener</code> class binds keys to actions.
* Bound actions include:
* b :: Toggle color-mapping for 0 energy crystals
* h :: Toggle selected crystal highlighting
* l :: Toggle logarithmic versus linear scaling
- * s :: Saves the current display to a file
+ * s :: Saves the current display to a file
**/
private class EcalKeyListener implements KeyListener {
+ @Override
public void keyPressed(KeyEvent e) { }
+ @Override
public void keyReleased(KeyEvent e) {
// 'b' toggles the default white background.
if(e.getKeyCode() == 66) {
- if(background) { ecalPanel.setDefaultCrystalColor(null); }
- else { ecalPanel.setDefaultCrystalColor(Color.GRAY); }
- background = !background;
+ if(background) { ecalPanel.setDefaultCrystalColor(null); }
+ else { ecalPanel.setDefaultCrystalColor(Color.GRAY); }
+ background = !background;
}
// 'h' toggles highlighting the crystal under the cursor.
@@ -132,39 +132,40 @@
// 'l' toggles linear or logarithmic scaling.
else if(e.getKeyCode() == 76) {
- if(ecalPanel.isScalingLinear()) { ecalPanel.setScalingLogarithmic(); }
- else { ecalPanel.setScalingLinear(); }
+ if(ecalPanel.isScalingLinear()) { ecalPanel.setScalingLogarithmic(); }
+ else { ecalPanel.setScalingLinear(); }
}
// 's' saves the panel to a file.
else if(e.getKeyCode() == 83) {
- // Make a new buffered image on which to draw the content pane.
- BufferedImage screenshot = new BufferedImage(getContentPane().getWidth(),
- getContentPane().getHeight(), BufferedImage.TYPE_INT_ARGB);
-
- // Paint the content pane to image.
- getContentPane().paint(screenshot.getGraphics());
-
- // Get the lowest available file name.
- int fileNum = 0;
- File imageFile = new File("screenshot_" + fileNum + ".png");
- while(imageFile.exists()) {
- fileNum++;
- imageFile = new File("screenshot_" + fileNum + ".png");
- }
-
- // Save the image to a PNG file.
- try { ImageIO.write(screenshot, "PNG", imageFile); }
- catch(IOException ioe) {
- System.err.println("Error saving file \"screenshot.png\".");
- }
- System.out.println("Screenshot saved to: " + imageFile.getAbsolutePath());
+ // Make a new buffered image on which to draw the content pane.
+ BufferedImage screenshot = new BufferedImage(getContentPane().getWidth(),
+ getContentPane().getHeight(), BufferedImage.TYPE_INT_ARGB);
+
+ // Paint the content pane to image.
+ getContentPane().paint(screenshot.getGraphics());
+
+ // Get the lowest available file name.
+ int fileNum = 0;
+ File imageFile = new File("screenshot_" + fileNum + ".png");
+ while(imageFile.exists()) {
+ fileNum++;
+ imageFile = new File("screenshot_" + fileNum + ".png");
+ }
+
+ // Save the image to a PNG file.
+ try { ImageIO.write(screenshot, "PNG", imageFile); }
+ catch(IOException ioe) {
+ System.err.println("Error saving file \"screenshot.png\".");
+ }
+ System.out.println("Screenshot saved to: " + imageFile.getAbsolutePath());
}
// Otherwise, print out the key code for the pressed key.
else { System.out.printf("Key Code: %d%n", e.getKeyCode()); }
}
+ @Override
public void keyTyped(KeyEvent e) { }
}
}
Modified: java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/POccupancyViewer.java
=============================================================================
--- java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/POccupancyViewer.java (original)
+++ java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/POccupancyViewer.java Sat Nov 1 02:29:56 2014
@@ -16,100 +16,93 @@
* @author Kyle McCarty
*/
public class POccupancyViewer extends PassiveViewer {
- private static final long serialVersionUID = 3712604287904215617L;
- // Store the number of hits for each crystal.
- private long[][] hits;
- // Store the total number of events read.
- private long events = 0;
- // Stores hit objects.
- protected ArrayList<EcalHit> hitList = new ArrayList<EcalHit>();
-
- /**
- * <b>POccupancyViewer</b><br/><br/>
- * <code>public <b>POccupancyViewer</b>(int updateRate, boolean resetAtUpdate)</code><br/><br/>
+ private static final long serialVersionUID = 3712604287904215617L;
+ // Store the number of hits for each crystal.
+ private long[][] hits;
+ // Store the total number of events read.
+ private long events = 0;
+ // Stores hit objects.
+ protected ArrayList<EcalHit> hitList = new ArrayList<EcalHit>();
+
+ /**
* Initializes a <code>Viewer</code> window that displays will
* occupancies from a data stream.
- */
- public POccupancyViewer() {
- // Set the title and scale.
- setTitle("HPS Calorimeter Occupancies");
- ecalPanel.setScaleMaximum(1.0);
-
- // Initialize the hit counts array.
- Dimension ecalSize = ecalPanel.getCrystalBounds();
- hits = new long[ecalSize.width][ecalSize.height];
- }
+ */
+ public POccupancyViewer() {
+ // Set the title and scale.
+ setTitle("HPS Calorimeter Occupancies");
+ ecalPanel.setScaleMaximum(1.0);
+
+ // Initialize the hit counts array.
+ Dimension ecalSize = ecalPanel.getCrystalBounds();
+ hits = new long[ecalSize.width][ecalSize.height];
+ }
- public void addHit(EcalHit hit) {
- // Get the panel coordinates of the hit.
- int ix = toPanelX(hit.getX());
- int iy = toPanelY(hit.getY());
-
- // Increment the hit count at the indicated location.
- hits[ix][iy]++;
- }
-
- /**
- * <b>addCluster</b><br/><br/>
- * <code>public void <b>addCluster</b>(Cluster cluster)</code><br/><br/>
- * Adds a new cluster to the display.<br/><br/>
- * <b>Note:</b> This operation is not supported for occupancies.
- */
- public void addCluster(Cluster cluster) { }
-
- /**
- * <b>removeHit</b><br/><br/>
- * <code>public void <b>removeHit</b>(EcalHit hit)</code><br/><br/>
- * Removes a hit from the display.
- * @param hit - The hit to be removed.
- */
- public void removeHit(EcalHit hit) {
- // Get the panel coordinates of the hit.
- int ix = toPanelX(hit.getX());
- int iy = toPanelY(hit.getY());
-
- // Decrement the hit count at the indicated location.
- hits[ix][iy]--;
- }
-
- public void resetDisplay() { hitList.clear(); }
-
- /**
- * <b>incrementEventCount</b><br/><br/>
- * <code>public void <b>incrementEventCount</b>(int amount)</code><br/><br/>
- * Increments the number of events represented by the current data
- * set by the indicated amount. Note that this may be negative to
- * reduce the number of events.
- * @param amount - The number of events to add.
- */
- public void incrementEventCount(int amount) { events += amount; }
-
- /**
- * <b>updateDisplay</b><br/><br/>
- * <code>public void <b>updateDisplay</b>()</code><br/><br/>
- * Displays the hits and clusters added by the <code>addHit</code>
- * and <code>addCluster</code> methods.
- */
- public void updateDisplay() {
+ @Override
+ public void addHit(EcalHit hit) {
+ // Get the panel coordinates of the hit.
+ int ix = toPanelX(hit.getX());
+ int iy = toPanelY(hit.getY());
+
+ // Increment the hit count at the indicated location.
+ hits[ix][iy]++;
+ }
+
+ /**
+ * Adds a new cluster to the display.<br/><br/>
+ * <b>Note:</b> This operation is not supported for occupancies.
+ */
+ public void addCluster(Cluster cluster) { }
+
+ /**
+ * Removes a hit from the display.
+ * @param hit - The hit to be removed.
+ */
+ public void removeHit(EcalHit hit) {
+ // Get the panel coordinates of the hit.
+ int ix = toPanelX(hit.getX());
+ int iy = toPanelY(hit.getY());
+
+ // Decrement the hit count at the indicated location.
+ hits[ix][iy]--;
+ }
+
+ @Override
+ public void resetDisplay() { hitList.clear(); }
+
+ /**
+ * Increments the number of events represented by the current data
+ * set by the indicated amount. Note that this may be negative to
+ * reduce the number of events.
+ * @param amount - The number of events to add.
+ */
+ public void incrementEventCount(int amount) { events += amount; }
+
+ /**
+ * Displays the hits and clusters added by the <code>addHit</code>
+ * and <code>addCluster</code> methods.
+ */
+ @Override
+ public void updateDisplay() {
// Build a "hit list" from the occupancies.
for(int x = 0; x < hits.length; x++) {
- for(int y = 0; y < hits[0].length; y++) {
- // Don't bother performing calculations or building
- // any objects if there are zero hits.
- if(hits[x][y] != 0) {
- // Define the crystal ID and "energy."
- Point cid = new Point(x, y);
- double occupancy = ((double) hits[x][y]) / events;
-
- // Add a "hit" formed from these values.
- hitList.add(new EcalHit(cid, occupancy));
- }
- }
+ for(int y = 0; y < hits[0].length; y++) {
+ // Don't bother performing calculations or building
+ // any objects if there are zero hits.
+ if(hits[x][y] != 0) {
+ // Define the crystal ID and "energy."
+ Point cid = new Point(x, y);
+ double occupancy = ((double) hits[x][y]) / events;
+
+ // Add a "hit" formed from these values.
+ hitList.add(new EcalHit(cid, occupancy));
+ }
+ }
}
- // Suppress the calorimeter panel's redrawing.
- ecalPanel.setSuppressRedraw(true);
-
+ // Suppress the calorimeter panel's redrawing.
+ ecalPanel.setSuppressRedraw(true);
+
// Display the hits.
for (EcalHit h : hitList) {
int ix = toPanelX(h.getX());
@@ -123,5 +116,5 @@
// Update the status panel to account for the new event.
updateStatusPanel();
- }
+ }
}
Modified: java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/PassiveViewer.java
=============================================================================
--- java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/PassiveViewer.java (original)
+++ java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/PassiveViewer.java Sat Nov 1 02:29:56 2014
@@ -20,94 +20,94 @@
* @author Kyle McCarty
*/
public abstract class PassiveViewer extends Viewer {
- private static final long serialVersionUID = -7479125553259270894L;
- // Stores whether the background color is set or not.
- private boolean background = false;
-
- /**
- * <b>PassiveViewer</b><br/><br/>
- * <code>public <b>PassiveViewer</b>(String... fieldValues)</code><br/><br/>
- * @param fieldValues
- */
- public PassiveViewer(String... fieldValues) {
- // Pass the field values to the superclass.
- super(fieldValues);
-
- // Set the key bindings.
- addKeyListener(new EcalKeyListener());
- }
-
- /**
- * <b>addHit</b><br/><br/>
- * <code>public void <b>addHit</b>(EcalHit hit)</code><br/><br/>
- * Adds a new hit to the display.
- * @param hit - The hit to be added.
- */
- public abstract void addHit(EcalHit hit);
-
- /**
- * <b>addCluster</b><br/><br/>
- * <code>public void <b>addCluster</b>(Cluster cluster)</code><br/><br/>
- * Adds a new cluster to the display.
- * @param cluster - The cluster to be added.
- */
- public abstract void addCluster(Cluster cluster);
-
- /**
- * <b>resetDisplay</b><br/><br/>
- * <code>public void <b>resetDisplay</b>()</code><br/><br/>
- * Clears any hits or clusters that have been added to the viewer.
- * Note that this does not automatically update the displayed panel.
- * <code>updateDisplay</code> must be called separately.
- */
- public abstract void resetDisplay();
-
- /**
- * <b>setScale</b><br/><br/>
- * <code>public void <b>setScale</b>(int min, int max)</code><br/><br/>
- * Sets the upper and lower bounds of for the calorimeter display's
- * color mapping scale.
- * @param min - The lower bound.
- * @param max - The upper bound.
- */
- public void setScale(int min, int max) {
- ecalPanel.setScaleMinimum(min);
- ecalPanel.setScaleMaximum(max);
- }
-
- /**
- * <b>setScaleMaximum</b><br/><br/>
- * <code>public void <b>setScaleMaximum</b>(int max)</code><br/><br/>
- * Sets the upper bound for the calorimeter display's color mapping
- * scale.
- * @param max - The upper bound.
- */
- public void setScaleMaximum(int max) { ecalPanel.setScaleMaximum(max); }
-
- /**
- * <b>setScaleMinimum</b><br/><br/>
- * <code>public void <b>setScaleMinimum</b>(int min)</code><br/><br/>
- * Sets the lower bound for the calorimeter display's color mapping
- * scale.
- * @param min - The lower bound.
- */
- public void setScaleMinimum(int min) { ecalPanel.setScaleMinimum(min); }
-
- /**
- * <b>updateDisplay</b><br/><br/>
- * <code>public void <b>updateDisplay</b>()</code><br/><br/>
- * Displays the hits and clusters added by the <code>addHit</code>
- * and <code>addCluster</code> methods.
- */
- public abstract void updateDisplay();
-
+ private static final long serialVersionUID = -7479125553259270894L;
+ // Stores whether the background color is set or not.
+ private boolean background = false;
+
+ /**
+ * <b>PassiveViewer</b><br/><br/>
+ * <code>public <b>PassiveViewer</b>(String... fieldValues)</code><br/><br/>
+ * @param fieldValues
+ */
+ public PassiveViewer() {
+ // Initialize the superclass.
+ super();
+
+ // Set the key bindings.
+ addKeyListener(new EcalKeyListener());
+ }
+
+ /**
+ * <b>addHit</b><br/><br/>
+ * <code>public void <b>addHit</b>(EcalHit hit)</code><br/><br/>
+ * Adds a new hit to the display.
+ * @param hit - The hit to be added.
+ */
+ public abstract void addHit(EcalHit hit);
+
+ /**
+ * <b>addCluster</b><br/><br/>
+ * <code>public void <b>addCluster</b>(Cluster cluster)</code><br/><br/>
+ * Adds a new cluster to the display.
+ * @param cluster - The cluster to be added.
+ */
+ public abstract void addCluster(Cluster cluster);
+
+ /**
+ * <b>resetDisplay</b><br/><br/>
+ * <code>public void <b>resetDisplay</b>()</code><br/><br/>
+ * Clears any hits or clusters that have been added to the viewer.
+ * Note that this does not automatically update the displayed panel.
+ * <code>updateDisplay</code> must be called separately.
+ */
+ public abstract void resetDisplay();
+
+ /**
+ * <b>setScale</b><br/><br/>
+ * <code>public void <b>setScale</b>(int min, int max)</code><br/><br/>
+ * Sets the upper and lower bounds of for the calorimeter display's
+ * color mapping scale.
+ * @param min - The lower bound.
+ * @param max - The upper bound.
+ */
+ public void setScale(int min, int max) {
+ ecalPanel.setScaleMinimum(min);
+ ecalPanel.setScaleMaximum(max);
+ }
+
+ /**
+ * <b>setScaleMaximum</b><br/><br/>
+ * <code>public void <b>setScaleMaximum</b>(int max)</code><br/><br/>
+ * Sets the upper bound for the calorimeter display's color mapping
+ * scale.
+ * @param max - The upper bound.
+ */
+ public void setScaleMaximum(int max) { ecalPanel.setScaleMaximum(max); }
+
+ /**
+ * <b>setScaleMinimum</b><br/><br/>
+ * <code>public void <b>setScaleMinimum</b>(int min)</code><br/><br/>
+ * Sets the lower bound for the calorimeter display's color mapping
+ * scale.
+ * @param min - The lower bound.
+ */
+ public void setScaleMinimum(int min) { ecalPanel.setScaleMinimum(min); }
+
+ /**
+ * <b>updateDisplay</b><br/><br/>
+ * <code>public void <b>updateDisplay</b>()</code><br/><br/>
+ * Displays the hits and clusters added by the <code>addHit</code>
+ * and <code>addCluster</code> methods.
+ */
+ public abstract void updateDisplay();
+
/**
* The <code>EcalListener</code> class binds keys to actions.
* Bound actions include:
* b :: Toggle color-mapping for 0 energy crystals
* h :: Toggle selected crystal highlighting
* l :: Toggle logarithmic versus linear scaling
- * s :: Saves the current display to a file
+ * s :: Saves the current display to a file
**/
private class EcalKeyListener implements KeyListener {
public void keyPressed(KeyEvent e) { }
@@ -115,9 +115,9 @@
public void keyReleased(KeyEvent e) {
// 'b' toggles the default white background.
if(e.getKeyCode() == 66) {
- if(background) { ecalPanel.setDefaultCrystalColor(null); }
- else { ecalPanel.setDefaultCrystalColor(Color.GRAY); }
- background = !background;
+ if(background) { ecalPanel.setDefaultCrystalColor(null); }
+ else { ecalPanel.setDefaultCrystalColor(Color.GRAY); }
+ background = !background;
}
// 'h' toggles highlighting the crystal under the cursor.
@@ -125,33 +125,33 @@
// 'l' toggles linear or logarithmic scaling.
else if(e.getKeyCode() == 76) {
- if(ecalPanel.isScalingLinear()) { ecalPanel.setScalingLogarithmic(); }
- else { ecalPanel.setScalingLinear(); }
+ if(ecalPanel.isScalingLinear()) { ecalPanel.setScalingLogarithmic(); }
+ else { ecalPanel.setScalingLinear(); }
}
// 's' saves the panel to a file.
else if(e.getKeyCode() == 83) {
- // Make a new buffered image on which to draw the content pane.
- BufferedImage screenshot = new BufferedImage(getContentPane().getWidth(),
- getContentPane().getHeight(), BufferedImage.TYPE_INT_ARGB);
-
- // Paint the content pane to image.
- getContentPane().paint(screenshot.getGraphics());
-
- // Get the lowest available file name.
- int fileNum = 0;
- File imageFile = new File("screenshot_" + fileNum + ".png");
- while(imageFile.exists()) {
- fileNum++;
- imageFile = new File("screenshot_" + fileNum + ".png");
- }
-
- // Save the image to a PNG file.
- try { ImageIO.write(screenshot, "PNG", imageFile); }
- catch(IOException ioe) {
- System.err.println("Error saving file \"screenshot.png\".");
- }
- System.out.println("Screenshot saved to: " + imageFile.getAbsolutePath());
+ // Make a new buffered image on which to draw the content pane.
+ BufferedImage screenshot = new BufferedImage(getContentPane().getWidth(),
+ getContentPane().getHeight(), BufferedImage.TYPE_INT_ARGB);
+
+ // Paint the content pane to image.
+ getContentPane().paint(screenshot.getGraphics());
+
+ // Get the lowest available file name.
+ int fileNum = 0;
+ File imageFile = new File("screenshot_" + fileNum + ".png");
+ while(imageFile.exists()) {
+ fileNum++;
+ imageFile = new File("screenshot_" + fileNum + ".png");
+ }
+
+ // Save the image to a PNG file.
+ try { ImageIO.write(screenshot, "PNG", imageFile); }
+ catch(IOException ioe) {
+ System.err.println("Error saving file \"screenshot.png\".");
+ }
+ System.out.println("Screenshot saved to: " + imageFile.getAbsolutePath());
}
// Otherwise, print out the key code for the pressed key.
Added: java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/ResizableFieldPanel.java
=============================================================================
--- java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/ResizableFieldPanel.java (added)
+++ java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/ResizableFieldPanel.java Sat Nov 1 02:29:56 2014
@@ -0,0 +1,515 @@
+package org.hps.monitoring.ecal.eventdisplay.ui;
+
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.LayoutManager;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+/**
+ * Class <code>ResizableFieldPanel</code> is an extension of <code>
+ * JPanel</code> that contains a series of "fields." Each field is
+ * composed of a header label that displays its name and a value
+ * label that displays its value. Field names are constant once set
+ * but values may be changed.<br/>
+ * <br/>
+ * <code>ResizableFieldPanel</code> automatically handles the layout
+ * of its fields, displaying the header label next to the value label
+ * and inserting as many in a row as possible before wrapping to the
+ * next row. <code>ResizableFieldPanel</code> ensures that each field
+ * in a column is the same size as the other fields in the same column
+ * and that all fields in the same column are aligned. Individual
+ * columns may be different widths.<br/>
+ * <br/>
+ * The preferred width of a column is set by the preferred size of the
+ * largest field in that column or a minimum row size, if it is set.
+ * Fields that exceed the minimum row size are still granted their full
+ * preferred size.
+ *
+ * @author Kyle McCarty
+ * @see JPanel
+ */
+public class ResizableFieldPanel extends JPanel {
+ // Local variables.
+ private static final long serialVersionUID = 1L;
+ private Font boldFont = getFont().deriveFont(Font.BOLD);
+ private static final int horizontal = 10;
+ private static final int vertical = 10;
+ private Dimension oldSize = new Dimension(0, 0);
+ private int oldFieldCount = 0;
+ private int minDisplayWidth = 0;
+ private Dimension userPreferred = null;
+ private Dimension actualPreferred = new Dimension(0, 0);
+
+ // Constituent components.
+ private List<JLabel> headerList = new ArrayList<JLabel>();
+ private List<JLabel> displayList = new ArrayList<JLabel>();
+
+ // Class variables.
+ /** The display text for a field with no value. */
+ static final String NULL_VALUE = "---";
+
+ /**
+ * Instantiates a new <code>ResizableFieldPanel</code> with no
+ * minimum column width.
+ */
+ public ResizableFieldPanel() { this(0); }
+
+ /**
+ * Instantiates a new <code>ResizableFieldPanel</code> with the
+ * indicated minimum column width.
+ * @param minWidth - The minimum column width.
+ */
+ public ResizableFieldPanel(int minWidth) {
+ // Component handles constituent component placement manually.
+ super.setLayout(null);
+
+ // Set the minimum component width.
+ minDisplayWidth = minWidth >= 0 ? minWidth : 0;
+
+ // Reset the constituent component placement whenever the base
+ // component changes size.
+ addComponentListener(new ComponentAdapter() {
+ @Override
+ public void componentResized(ComponentEvent e) {
+ // Issue an order to reset the component layout.
+ resetLayout();
+ }
+ });
+ }
+
+ /**
+ * Adds a new field to the panel.
+ * @param fieldName - The name of the field.
+ * @throws NullPointerException Occurs if the field name is <code>
+ * null</code>.
+ */
+ public void addField(String fieldName) throws NullPointerException {
+ addField(fieldName, null);
+ }
+
+ /**
+ * Adds a new field to the panel.
+ * @param fieldName - The name of the field.
+ * @param fieldValue - The initial value of the field.
+ * @throws NullPointerException Occurs if the field name is <code>
+ * null</code>.
+ */
+ public void addField(String fieldName, String fieldValue) throws NullPointerException {
+ // Require that the field have a non-null name.
+ if(fieldName == null) { throw new NullPointerException("Field names can not be null."); }
+
+ // Null values default the default value.
+ if(fieldValue == null) { fieldValue = NULL_VALUE; }
+
+ // Create new labels to populate the component.
+ JLabel header = new JLabel(fieldName + ":");
+ header.setFont(boldFont);
+ header.setHorizontalAlignment(JLabel.RIGHT);
+ JLabel display = new JLabel(fieldValue);
+ display.setFont(getFont());
+
+ // Add the labels to the list.
+ headerList.add(header);
+ displayList.add(display);
+
+ // Add the components to the base panel.
+ add(header);
+ add(display);
+
+ // Reset the label layout.
+ resetLayout();
+ }
+
+ /**
+ * Sets the values of all fields to <code>NULL_VALUE</code>.
+ */
+ public void clearFields() {
+ for(JLabel display : displayList) {
+ display.setText(NULL_VALUE);
+ }
+ }
+
+ /**
+ * Gets the number of fields contained in the component.
+ * @return Returns the number of fields as an <code>int</code>
+ * primitive.
+ */
+ public int getFieldCount() { return headerList.size(); }
+
+ /**
+ * Generates a map that links field name to field index.
+ * @return Returns a <code>Map</code> object linking the <code>
+ * String</code> field name to the <code>int</code> field index.
+ */
+ public Map<String, Integer> getFieldNameIndexMap() {
+ // Get the number of fields.
+ int fields = headerList.size();
+
+ // Create the map.
+ Map<String, Integer> fieldMap = new HashMap<String, Integer>(fields);
+
+ // Populate the map.
+ for(int index = 0; index < fields; index++) {
+ // Get the header name and remove the colon at the end.
+ String header = headerList.get(index).getText();
+ header = header.substring(0, header.length() - 1);
+
+ // Add it to the map.
+ fieldMap.put(header, new Integer(index));
+ }
+
+ // Return the map.
+ return fieldMap;
+ }
+
+ /**
+ * Gets the list of all field names in order of field index.
+ * @return Returns the set of field names as an array of <code>
+ * String</code> objects.
+ */
+ public String[] getFieldNames() {
+ // Create an array for the field names.
+ String[] fieldNames = new String[headerList.size()];
+
+ // Populate the array.
+ for(int index = 0; index < headerList.size(); index++) {
+ String fieldName = headerList.get(index).getText();
+ fieldNames[index] = fieldName.substring(0, fieldName.length() - 2);
+ }
+
+ // Return the result.
+ return fieldNames;
+ }
+
+ /**
+ * Gets the value for the field at the indicated index.
+ * @param fieldIndex - The index of the field.
+ * @return Returns the field value as a <code>String</code> object.
+ * @throws IndexOutOfBoundsException Occurs if an invalid field index
+ * is given.
+ */
+ public String getFieldValue(int fieldIndex) throws IndexOutOfBoundsException {
+ // Validate the index.
+ validateFieldIndex(fieldIndex);
+
+ // Return the value of the requested field.
+ return displayList.get(fieldIndex).getText();
+ }
+
+ @Override
+ public Dimension getPreferredSize() {
+ if(userPreferred == null) { return actualPreferred; }
+ else { return userPreferred; }
+ }
+
+ /**
+ * Inserts a field at the indicated index, if possible.
+ * @param index - The index at which to insert the field.
+ * @param fieldName - The name of the field.
+ * @throws IndexOutOfBoundsException Occurs if the insertion index
+ * is not a valid index within the component.
+ * @throws NullPointerException Occurs if the field name is <code>
+ * null</code>.
+ */
+ public void insertField(int index, String fieldName) throws IndexOutOfBoundsException, NullPointerException {
+ insertField(index, fieldName, "");
+ }
+
+ /**
+ * Inserts a field at the indicated index, if possible.
+ * @param index - The index at which to insert the field.
+ * @param fieldName - The name of the field.
+ * @param fieldValue - The initial value of the field.
+ * @throws IndexOutOfBoundsException Occurs if the insertion index
+ * is not a valid index within the component.
+ * @throws NullPointerException Occurs if the field name is <code>
+ * null</code>.
+ */
+ public void insertField(int index, String fieldName, String fieldValue) throws IndexOutOfBoundsException, NullPointerException {
+ // Require that the field have a non-null name.
+ if(fieldName == null) { throw new NullPointerException("Field names can not be null."); }
+
+ // Null values default the default value.
+ if(fieldValue == null) { fieldValue = NULL_VALUE; }
+
+ // Create new labels to populate the component.
+ JLabel header = new JLabel(fieldName + ":");
+ header.setFont(boldFont);
+ header.setHorizontalAlignment(JLabel.RIGHT);
+ JLabel display = new JLabel(fieldValue);
+ display.setFont(getFont());
+
+ // Add the labels to the list.
+ headerList.add(index, header);
+ displayList.add(index, display);
+
+ // Add the components to the base panel.
+ add(header);
+ add(display);
+
+ // Reset the label layout.
+ resetLayout();
+ }
+
+ /**
+ * Removes the field at the indicated index.
+ * @param fieldIndex - The index of the field.
+ * @throws IndexOutOfBoundsException Occurs if an invalid field index
+ * is given.
+ */
+ public void removeField(int fieldIndex) throws IndexOutOfBoundsException {
+ // Validate the index.
+ validateFieldIndex(fieldIndex);
+
+ // Remove the requested field.
+ remove(headerList.get(fieldIndex));
+ remove(displayList.get(fieldIndex));
+ headerList.remove(fieldIndex);
+ displayList.remove(fieldIndex);
+
+ // Reset the layout.
+ resetLayout();
+ }
+
+ /**
+ * Sets the value of the field at the indicated index.
+ * @param fieldIndex - The index of the field.
+ * @param fieldValue - The new value of the field.
+ * @throws IndexOutOfBoundsException Occurs if an invalid field index
+ * is given.
+ */
+ public void setFieldValue(int fieldIndex, String fieldValue) throws IndexOutOfBoundsException {
+ // Validate the index.
+ validateFieldIndex(fieldIndex);
+
+ // Set the value of the requested field.
+ displayList.get(fieldIndex).setText(fieldValue);
+ }
+
+ @Override
+ public void setFont(Font font) {
+ // If the superclass font is null, the component is still
+ // being initialized and needs to just run the superclass
+ // method.
+ if(getFont() == null) { super.setFont(font); }
+
+ // Otherwise, set any constituent components to the correct
+ // font as well.
+ else {
+ // If the font is being set to null, use the default
+ // system font.
+ if(font == null) { font = new Font(Font.DIALOG, Font.PLAIN, 11); }
+
+ // Set the base panel's font to the indicated value.
+ super.setFont(font);
+
+ // Create a new bold font.
+ boldFont = super.getFont().deriveFont(Font.BOLD);
+
+ // Set each display label to the indicated font.
+ for(JLabel display : displayList) { display.setFont(font); }
+
+ // Set each header label to the bold font.
+ for(JLabel header : headerList) { header.setFont(boldFont); }
+ }
+ }
+
+ @Override
+ public void setLayout(LayoutManager mgr) {
+ // ResizableDisplayManager handles its own layout, so do nothing.
+ return;
+ }
+
+ @Override
+ public void setPreferredSize(Dimension preferredSize) {
+ userPreferred = preferredSize;
+ }
+
+ /**
+ * Repositions the fields to the appropriate positions given the
+ * current width of the component.
+ */
+ private void resetLayout() {
+ // If the neither the size of the component nor the number of
+ // fields have changed, there is nothing to do here.
+ if(headerList.size() == oldFieldCount && oldSize.width == getSize().width
+ && oldSize.height == getSize().height) {
+ return;
+ }
+
+ // Set the last width and field counts.
+ oldSize = getSize();
+ oldFieldCount = headerList.size();
+
+ // Otherwise, determine the ideal maximum number of fields that
+ // can be displayed in a single row.
+ int availableWidth = getWidth() - horizontal;
+ int max = 0;
+ idealLoop:
+ for(int index = 0; index < headerList.size(); index++) {
+ // Subtract the necessary width for the header label.
+ availableWidth -= headerList.get(index).getPreferredSize().width;
+ availableWidth -= horizontal;
+
+ // Subtract the required width for the display label.
+ int displayWidth = displayList.get(index).getPreferredSize().width;
+ if(displayWidth < minDisplayWidth) { displayWidth = minDisplayWidth; }
+ availableWidth -= displayWidth;
+ availableWidth -= horizontal;
+
+ // Increment the maximum number of displayable headers.
+ max++;
+
+ // If the available width is depleted, exit the loop.
+ if(availableWidth <= 0) { break idealLoop; }
+ }
+
+ // If the maximum displayable number is either 1 or equal to
+ // actual number, the fields should be displayed with their
+ // preferred widths.
+ if(max == 1 || max == headerList.size()) {
+ // Track the current position on the component.
+ int curX = horizontal;
+ int curY = vertical;
+
+ // Add each field.
+ for(int index = 0; index < headerList.size(); index++) {
+ // Get the current header and display label.
+ JLabel header = headerList.get(index);
+ JLabel display = displayList.get(index);
+
+ // Set the label sizes to the preferred size.
+ header.setSize(header.getPreferredSize());
+ display.setSize(display.getPreferredSize());
+
+ // Set the label locations to the current correct place.
+ header.setLocation(curX, curY);
+ header.setSize(header.getPreferredSize());
+ curX += header.getSize().width + horizontal;
+ display.setLocation(curX, curY);
+ display.setSize(header.getPreferredSize());
+ curX += display.getWidth() + horizontal;
+ }
+
+ // The process is finished, so return.
+ return;
+ }
+
+ // Otherwise, the labels in subsequent rows must be analyzed
+ // to determine what the actual maximum number of labels per
+ // row can be used. Try the ideal maximum first and work down
+ // from there to the minimum of one per row.
+ else {
+ // Track the number of columns needed and the proper widths
+ // of each column.
+ int columns = 1;
+ int[] columnWidth = { 0 };
+ actualLoop:
+ for(int actual = max; actual > 0; actual--) {
+ // Store the actual necessary width for each component in
+ // each column for the current row size.
+ int[] actualColWidth = new int[actual + actual];
+
+ // Track the current column.
+ int curCol = 0;
+
+ // Iterate over the labels and find the largest necessary
+ // width for each column.
+ for(int index = 0; index < headerList.size(); index++) {
+ // Get the widths needed for the current header and
+ // display labels.
+ int headerWidth = headerList.get(index).getPreferredSize().width;
+ int displayWidth = displayList.get(index).getPreferredSize().width;
+ if(displayWidth < minDisplayWidth) { displayWidth = minDisplayWidth; }
+
+ // If the needed widths exceed the current maximum, they
+ // should replace it.
+ if(actualColWidth[2 * curCol] < headerWidth) { actualColWidth[2 * curCol] = headerWidth; }
+ if(actualColWidth[(2 * curCol) + 1] < displayWidth) { actualColWidth[(2 * curCol) + 1] = displayWidth; }
+
+ // Increment the current column.
+ curCol++;
+ if(curCol == actual) { curCol = 0; }
+ }
+
+ // Check if the actual needed width is less than the width
+ // available for the labels.
+ availableWidth = getWidth() - horizontal;
+ for(int width : actualColWidth) {
+ availableWidth -= width;
+ availableWidth -= horizontal;
+ }
+
+ // Store the results for this number of columns.
+ columns = actual;
+ columnWidth = actualColWidth;
+
+ // If the result is either zero of positive, then there is
+ // enough space available and the current number of columns
+ // may be employed. Otherwise, continue to the next smaller
+ // number of columns.
+ if(availableWidth >= 0) { break actualLoop; }
+ }
+
+ // The necessary width for each column and the number of columns
+ // should now be calculated. Set the constituent component
+ // positions and sizes to match it.
+ int curX = horizontal;
+ int curY = vertical;
+ int curCol = 0;
+ for(int index = 0; index < headerList.size(); index++) {
+ // Get the current header and display label.
+ JLabel header = headerList.get(index);
+ JLabel display = displayList.get(index);
+
+ // Set the label sizes to the preferred size.
+ header.setSize(header.getPreferredSize());
+ display.setSize(display.getPreferredSize());
+
+ // Set the label locations to the current correct place.
+ header.setLocation(curX, curY);
+ header.setSize(columnWidth[2 * curCol], header.getPreferredSize().height);
+ curX += header.getSize().width + horizontal;
+ display.setLocation(curX, curY);
+ display.setSize(columnWidth[(2 * curCol) + 1], display.getPreferredSize().height);
+ curX += display.getWidth() + horizontal;
+
+ // Increment the current column index.
+ curCol++;
+ if(curCol == columns) {
+ curCol = 0;
+ curY += header.getPreferredSize().height + vertical;
+ curX = horizontal;
+ }
+ }
+ }
+
+ // Update the preferred size such that the preferred height will
+ // encompass all of the rows.
+ JLabel lastHeader = headerList.get(headerList.size() - 1);
+ int preferredHeight = lastHeader.getY() + lastHeader.getHeight() + vertical;
+ actualPreferred = new Dimension(getSize().width, preferredHeight);
+ }
+
+ /**
+ * Throws an <code>IndexOutOfBoundsException</code> if the argument
+ * index is not a valid field index. This is used to validate the
+ * index given in methods requiring one.
+ * @param index - The index to validate.
+ * @throws IndexOutOfBoundsException Occurs if the index fails
+ * to validate.
+ */
+ private void validateFieldIndex(int index) throws IndexOutOfBoundsException {
+ if(index < 0 || index >= headerList.size()) {
+ throw new IndexOutOfBoundsException(String.format("Index %d is not a valid field index.", index));
+ }
+ }
+}
Modified: java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/StatusPanel.java
=============================================================================
--- java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/StatusPanel.java (original)
+++ java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/StatusPanel.java Sat Nov 1 02:29:56 2014
@@ -9,188 +9,180 @@
/**
* Class <code>StatusPanel</code> displays text in a set of fields.
+ * This class is being phased out in favor of <code>ResizableFieldPanel
+ * </code> and should no longer be used. It will be removed next update.
*
* @author Kyle McCarty
*/
+@Deprecated
public class StatusPanel extends JPanel {
- private static final long serialVersionUID = -8353479383875379010L;
- // The panel that displays behind the status field.
- private BackPanel background = new BackPanel();
- // The status fields. The first array index represents which status
- // field and the second is always of size two, with index 0 mapping
- // to the label that displays the field name and index 1 mapping to
- // the label displaying the field value.
- private JLabel[][] field;
- // Spacing variables for panel layout.
- private int leftBuffer = 10;
- private int upperBuffer = 10;
-
- /**
- * <b>NULL_VALUE</b><br/><br/>
- * <code><b>static final String <b>NULL_VALUE</b></code><br/><br/>
- * A <code>String</code> representing the default value to be
- * displayed on the status panel whenever there is no value for
- * that field.
- */
- static final String NULL_VALUE = "---";
-
- /**
- * <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] + ": ");
- field[i][0].setHorizontalAlignment(JLabel.RIGHT);
- }
-
- // Start the fields as null by default.
- clearValues();
-
- // Build the background panel.
- add(background);
- setComponentZOrder(background, curZ);
- }
-
- /**
- * <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(NULL_VALUE);
- }
- }
-
- /**
- * <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(NULL_VALUE); }
- 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>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;
- }
-
- /**
- * <b>resize</b><br/><br/>
- * <code>private void <b>resize</b>()</code><br/><br/>
- * Updates the layout of the component to the panel's current size.
- */
- 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)) / 3;
- int labelRem = (height - upperBuffer - 8) % field.length;
- int curX = leftBuffer;
- 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(curX, curY, 130, thisHeight);
- field[i][1].setBounds(getNextX(field[i][0]), curY, 75, thisHeight);
-
- // If we have written three labels, then start a new column.
- if(i % 3 == 2) {
- curX = getNextX(field[i][1], 10);
- curY = (int)(upperBuffer + 2);
- }
-
- // Otherwise just increment the current height.
- else { curY += thisHeight; }
- }
- }
- }
-
- /**
- * Class <code>BackPanel</code> simply renders the background panel
- * for the status panel.
- */
- private class BackPanel extends JPanel {
- private static final long serialVersionUID = 4997805650267243080L;
+ private static final long serialVersionUID = -8353479383875379010L;
+ // The panel that displays behind the status field.
+ private BackPanel background = new BackPanel();
+ // The status fields. The first array index represents which status
+ // field and the second is always of size two, with index 0 mapping
+ // to the label that displays the field name and index 1 mapping to
+ // the label displaying the field value.
+ private JLabel[][] field;
+ // Spacing variables for panel layout.
+ private int leftBuffer = 10;
+ private int upperBuffer = 10;
+
+ /**
+ * A <code>String</code> representing the default value to be
+ * displayed on the status panel whenever there is no value for
+ * that field.
+ */
+ static final String NULL_VALUE = "---";
+
+ /**
+ * 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] + ": ");
+ field[i][0].setHorizontalAlignment(JLabel.RIGHT);
+ }
+
+ // Start the fields as null by default.
+ clearValues();
+
+ // Build the background panel.
+ add(background);
+ setComponentZOrder(background, curZ);
+ }
+
+ /**
+ * 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(NULL_VALUE);
+ }
+ }
+
+ /**
+ * 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(NULL_VALUE); }
+ else { field[index][1].setText(value); }
+ }
+ else { throw new IndexOutOfBoundsException("Invalid field index."); }
+ }
+
+ @Override
+ public void setSize(int width, int height) {
+ super.setSize(width, height);
+ resize();
+ }
+
+ @Override
+ public void setSize(Dimension d) {
+ super.setSize(d);
+ resize();
+ }
+
+ /**
+ * 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); }
+
+ /**
+ /**
+ * 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;
+ }
+
+ /**
+ * Updates the layout of the component to the panel's current size.
+ */
+ 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)) / 3;
+ int labelRem = (height - upperBuffer - 8) % field.length;
+ int curX = leftBuffer;
+ 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(curX, curY, 130, thisHeight);
+ field[i][1].setBounds(getNextX(field[i][0]), curY, 75, thisHeight);
+
+ // If we have written three labels, then start a new column.
+ if(i % 3 == 2) {
+ curX = getNextX(field[i][1], 10);
+ curY = (int)(upperBuffer + 2);
+ }
+
+ // Otherwise just increment the current height.
+ else { curY += thisHeight; }
+ }
+ }
+ }
+
+ /**
+ * 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);
- }
- }
+ 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);
+ }
+ }
}
Modified: java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/Viewer.java
=============================================================================
--- java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/Viewer.java (original)
+++ java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/Viewer.java Sat Nov 1 02:29:56 2014
@@ -11,6 +11,7 @@
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.Map;
import java.util.NoSuchElementException;
import javax.swing.JFrame;
@@ -30,7 +31,7 @@
// Java-suggested variable.
private static final long serialVersionUID = -2022819652687941812L;
// A map of field names to field indices.
- private final HashMap<String, Integer> fieldMap = new HashMap<String, Integer>();
+ private Map<String, Integer> fieldMap = new HashMap<String, Integer>();
// A list of crystal listeners attached to the viewer.
private ArrayList<CrystalListener> listenerList = new ArrayList<CrystalListener>();
// The default field names.
@@ -41,33 +42,25 @@
private static final int CELL_VALUE = 2;
/**
- * <b><statusPanel/b><br/><br/>
- * <code>protected final StatusPanel <b>statusPanel</b></code><br/><br/>
* The component responsible for displaying status information
* about the currently selected crystal.
*/
- protected final StatusPanel statusPanel;
-
- /**
- * <b>ecalPanel</b><br/><br/>
- * <code>protected final CalorimeterPanel <b>ecalPanel</b></code><br/><br/>
+ protected final ResizableFieldPanel statusPanel;
+
+ /**
* The panel displaying the calorimeter crystals and scale.
*/
protected final CalorimeterPanel ecalPanel = new CalorimeterPanel(46, 11);
-
- /**
- * <b>HIGHLIGHT_CLUSTER_COMPONENT</b><br/><br/>
- * <code>public static final Color <b>HIGHLIGHT_CLUSTER_COMPONENT</b></code><br/><br/>
+
+ /**
* The default color for highlighting cluster components.
*/
- public static final Color HIGHLIGHT_CLUSTER_COMPONENT = Color.RED;
-
- /**
- * <b>HIGHLIGHT_CLUSTER_SHARED</b><br/><br/>
- * <code>public static final Color <b>HIGHLIGHT_CLUSTER_SHARED</b></code><br/><br/>
+ public static final Color HIGHLIGHT_CLUSTER_COMPONENT = Color.RED;
+
+ /**
* The default color for highlighting cluster shared hits.
- */
- public static final Color HIGHLIGHT_CLUSTER_SHARED = Color.YELLOW;
+ */
+ public static final Color HIGHLIGHT_CLUSTER_SHARED = Color.YELLOW;
/**
* Initializes the viewer window and calorimeter panel.
@@ -76,29 +69,20 @@
* @throws NullPointerException Occurs if any of the additional field
* arguments are <code>null</code>.
**/
- public Viewer(String... statusFields) throws NullPointerException {
+ public Viewer() throws NullPointerException {
// Initialize the underlying JPanel.
super();
- // Define the status panel fields and map them to indices.
- String[] fields = new String[statusFields.length + defaultFields.length];
- for(int i = 0; i < defaultFields.length; i++) {
- fields[i] = defaultFields[i];
- fieldMap.put(defaultFields[i], i);
- }
- for(int i = 0; i < statusFields.length; i++) {
- int index = i + defaultFields.length;
- fields[index] = statusFields[i];
- fieldMap.put(statusFields[i], index);
- }
-
// Generate the status panel.
- statusPanel = new StatusPanel(fields);
+ statusPanel = new ResizableFieldPanel(100);
+ statusPanel.setBackground(Color.WHITE);
+
+ // Add the default fields.
+ for(String field : defaultFields) { addStatusField(field); }
// Set the scaling settings.
- ecalPanel.setScaleMinimum(0.00001);
- ecalPanel.setScaleMaximum(3);
- // ecalPanel.setScalingLogarithmic();
+ ecalPanel.setScaleMinimum(0.001);
+ ecalPanel.setScaleMaximum(3.0);
ecalPanel.setScalingLinear();
// Disable the crystals in the calorimeter panel along the beam gap.
@@ -137,7 +121,28 @@
* @param cl - The listener to add.
*/
public void addCrystalListener(CrystalListener cl) {
- if(cl != null) { listenerList.add(cl); }
+ if(cl != null) { listenerList.add(cl); }
+ }
+
+ /**
+ * Adds a new field to the status panel.
+ * @param fieldName - The name to display for the field and that
+ * links to the field when calling <code>setStatusField</code>.
+ */
+ protected void addStatusField(String fieldName) {
+ fieldMap.put(fieldName, statusPanel.getFieldCount());
+ statusPanel.addField(fieldName);
+ }
+
+ /**
+ * Inserts the field at the indicated location on the status panel.
+ * @param index - The index at which to insert the field.
+ * @param fieldName - The name to display for the field and that
+ * links to the field when calling <code>setStatusField</code>.
+ */
+ protected void insertStatusField(int index, String fieldName) {
+ statusPanel.insertField(index, fieldName);
+ fieldMap = statusPanel.getFieldNameIndexMap();
}
/**
@@ -147,14 +152,14 @@
* @return Returns the coordinate pair in LCSim's coordinate system
* as an <code>int</code>.
**/
- public static final Point toEcalPoint(Point panelPoint) {
- // Convert the point coordinates.
- int ix = toEcalX(panelPoint.x);
- int iy = toEcalY(panelPoint.y);
-
- // Return the new point.
- return new Point(ix, iy);
- }
+ public static final Point toEcalPoint(Point panelPoint) {
+ // Convert the point coordinates.
+ int ix = toEcalX(panelPoint.x);
+ int iy = toEcalY(panelPoint.y);
+
+ // Return the new point.
+ return new Point(ix, iy);
+ }
/**
* Converts the panel x-coordinate to the calorimeter's
@@ -164,8 +169,8 @@
* coordinate system as an <code>int</code>.
*/
public static final int toEcalX(int panelX) {
- if(panelX > 22) { return panelX - 22; }
- else { return panelX - 23; }
+ if(panelX > 22) { return panelX - 22; }
+ else { return panelX - 23; }
}
/**
@@ -184,14 +189,14 @@
* @return Returns the coordinate pair in the calorimeter panel's
* coordinate system as an <code>int</code>.
**/
- public static final Point toPanelPoint(Point ecalPoint) {
- // Convert the point coordinates.
- int ix = toPanelX(ecalPoint.x);
- int iy = toPanelY(ecalPoint.y);
-
- // Return the new point.
- return new Point(ix, iy);
- }
+ public static final Point toPanelPoint(Point ecalPoint) {
+ // Convert the point coordinates.
+ int ix = toPanelX(ecalPoint.x);
+ int iy = toPanelY(ecalPoint.y);
+
+ // Return the new point.
+ return new Point(ix, iy);
+ }
/**
* Converts the LCSim x-coordinate to the calorimeter panel's
@@ -238,7 +243,7 @@
* @param cl - The listener to remove.
*/
public void removeCrystalListener(CrystalListener cl) {
- if(cl != null) { listenerList.remove(cl); }
+ if(cl != null) { listenerList.remove(cl); }
}
public void setSize(int width, int height) {
@@ -259,44 +264,46 @@
* is provided for argument <code>fieldName</code>.
*/
public final void setStatusField(String fieldName, String value) throws NoSuchElementException {
- // Get the index for the indicated field.
- Integer index = fieldMap.get(fieldName);
-
- // If it is null, the field does not exist.
- if(index == null) { throw new NoSuchElementException("Field \"" + fieldName + "\" does not exist."); }
-
- // Otherwise, set the field.
- else { statusPanel.setFieldValue(index, value); }
- }
-
- /**
- * Updates the information on the status panel to match that of
- * the calorimeter panel's currently selected crystal.
- */
- protected void updateStatusPanel() {
- // Get the currently selected crystal.
- Point crystal = ecalPanel.getSelectedCrystal();
-
- // If the crystal is null, there is no selection.
- if(crystal == null || ecalPanel.isCrystalDisabled(crystal.x, crystal.y)) { statusPanel.clearValues(); }
-
- // Otherwise, write the crystal's data to the panel.
- else {
- setStatusField(defaultFields[X_INDEX], String.valueOf(toEcalX(crystal.x)));
- setStatusField(defaultFields[Y_INDEX], String.valueOf(toEcalY(crystal.y)));
- DecimalFormat formatter = new DecimalFormat("0.####E0");
- String energy = formatter.format(ecalPanel.getCrystalEnergy(crystal.x, crystal.y));
- setStatusField(defaultFields[CELL_VALUE], energy);
- }
- }
+ // Get the index for the indicated field.
+ Integer index = fieldMap.get(fieldName);
+
+ // If it is null, the field does not exist.
+ if(index == null) { throw new NoSuchElementException("Field \"" + fieldName + "\" does not exist."); }
+
+ // Otherwise, set the field.
+ else { statusPanel.setFieldValue(index, value); }
+ }
+
+ /**
+ * Updates the information on the status panel to match that of
+ * the calorimeter panel's currently selected crystal.
+ */
+ protected void updateStatusPanel() {
+ // Get the currently selected crystal.
+ Point crystal = ecalPanel.getSelectedCrystal();
+
+ // If the crystal is null, there is no selection.
+ if(crystal == null || ecalPanel.isCrystalDisabled(crystal.x, crystal.y)) {
+ statusPanel.clearFields();
+ }
+
+ // Otherwise, write the crystal's data to the panel.
+ else {
+ setStatusField(defaultFields[X_INDEX], String.valueOf(toEcalX(crystal.x)));
+ setStatusField(defaultFields[Y_INDEX], String.valueOf(toEcalY(crystal.y)));
+ DecimalFormat formatter = new DecimalFormat("0.####E0");
+ String energy = formatter.format(ecalPanel.getCrystalEnergy(crystal.x, crystal.y));
+ setStatusField(defaultFields[CELL_VALUE], energy);
+ }
+ }
/**
* Handles proper resizing of the window and its components.
**/
private void resize() {
- // Define the size constants.
- int statusHeight = 125;
-
+ // Define the size constants.
+ int statusHeight = 125;
+
// Size and position the calorimeter display.
ecalPanel.setLocation(0, 0);
ecalPanel.setSize(getContentPane().getWidth(), getContentPane().getHeight() - statusHeight);
@@ -312,30 +319,30 @@
* It also triggers crystal click events.
*/
private class EcalMouseListener implements MouseListener {
- public void mouseClicked(MouseEvent e) {
- // If there is a selected crystal, trigger a crystal click event.
- if(ecalPanel.getSelectedCrystal() != null) {
- // Get the selected crystal.
- Point crystal = ecalPanel.getSelectedCrystal();
-
- // Construct a crystal event.
- CrystalEvent ce = new CrystalEvent(Viewer.this, crystal);
-
- // Loop through all the crystal listeners and trigger them.
- for(CrystalListener cl : listenerList) { cl.crystalClicked(ce); }
- }
- }
-
- public void mouseEntered(MouseEvent e) { }
-
- public void mouseExited(MouseEvent e) {
- ecalPanel.clearSelectedCrystal();
- statusPanel.clearValues();
- }
-
- public void mousePressed(MouseEvent e) { }
-
- public void mouseReleased(MouseEvent e) { }
+ public void mouseClicked(MouseEvent e) {
+ // If there is a selected crystal, trigger a crystal click event.
+ if(ecalPanel.getSelectedCrystal() != null) {
+ // Get the selected crystal.
+ Point crystal = ecalPanel.getSelectedCrystal();
+
+ // Construct a crystal event.
+ CrystalEvent ce = new CrystalEvent(Viewer.this, crystal);
+
+ // Loop through all the crystal listeners and trigger them.
+ for(CrystalListener cl : listenerList) { cl.crystalClicked(ce); }
+ }
+ }
+
+ public void mouseEntered(MouseEvent e) { }
+
+ public void mouseExited(MouseEvent e) {
+ ecalPanel.clearSelectedCrystal();
+ statusPanel.clearFields();
+ }
+
+ public void mousePressed(MouseEvent e) { }
+
+ public void mouseReleased(MouseEvent e) { }
}
/**
@@ -344,80 +351,80 @@
* mouse moves over the window. Additionally triggers crystal
* activation and deactivation events.
*/
- private class EcalMouseMotionListener implements MouseMotionListener {
- public void mouseDragged(MouseEvent arg0) { }
-
- public void mouseMoved(MouseEvent e) {
- // Get the panel coordinates.
- int x = e.getX();
- int y = e.getY();
-
- // Get the crystal index for these coordinates.
- Point crystal = ecalPanel.getCrystalID(x, y);
-
- // If either of the crystal indices are negative, then
- // the mouse is not in a crystal and the selection should
- // be cleared.
- boolean validCrystal = (crystal != null);
-
- // Get the currently selected calorimeter crystal.
- Point curCrystal = ecalPanel.getSelectedCrystal();
-
- // Perform event comparison checks.
- boolean[] nullCrystal = { !validCrystal, curCrystal == null };
- boolean[] disabledCrystal = { true, true };
- if(!nullCrystal[0]) { disabledCrystal[0] = ecalPanel.isCrystalDisabled(crystal); }
- if(!nullCrystal[1]) { disabledCrystal[1] = ecalPanel.isCrystalDisabled(curCrystal); }
- boolean sameCrystal = true;
- if(validCrystal) { sameCrystal = crystal.equals(curCrystal); }
-
- // If the crystals are the same, there are no events to throw.
- if(!sameCrystal) {
- // If the new crystal is non-null and enabled, throw an event.
- if(!nullCrystal[0] && !disabledCrystal[0]) { throwActivationEvent(crystal); }
-
- // If the old crystal is non-null and enabled, throw an event.
- if(!nullCrystal[1] && !disabledCrystal[1]) { throwDeactivationEvent(curCrystal); }
- }
-
- // If the crystal is valid, then set the selected crystal
- // to the current one.
- if(validCrystal) { ecalPanel.setSelectedCrystal(crystal); }
-
- // Otherwise, clear the selection.
- else { ecalPanel.clearSelectedCrystal(); }
-
- // Update the status panel.
- updateStatusPanel();
- }
-
- /**
- * Triggers crystal activation events on all listeners for
- * this component.
- * @param activatedCrystal - The panel coordinates for the
- * activated crystal.
- */
- private void throwActivationEvent(Point activatedCrystal) {
- // Create a crystal event.
- CrystalEvent ce = new CrystalEvent(Viewer.this, activatedCrystal);
-
- // Throw the event with every listener.
- for(CrystalListener cl : listenerList) { cl.crystalActivated(ce); }
- }
-
- /**
- * Triggers crystal deactivation events on all listeners for
- * this component.
- * @param deactivatedCrystal - The panel coordinates for the
- * deactivated crystal.
- */
- private void throwDeactivationEvent(Point deactivatedCrystal) {
- // Create a crystal event.
- CrystalEvent ce = new CrystalEvent(Viewer.this, deactivatedCrystal);
-
- // Throw the event with every listener.
- for(CrystalListener cl : listenerList) { cl.crystalDeactivated(ce); }
- }
+ private class EcalMouseMotionListener implements MouseMotionListener {
+ public void mouseDragged(MouseEvent arg0) { }
+
+ public void mouseMoved(MouseEvent e) {
+ // Get the panel coordinates.
+ int x = e.getX();
+ int y = e.getY();
+
+ // Get the crystal index for these coordinates.
+ Point crystal = ecalPanel.getCrystalID(x, y);
+
+ // If either of the crystal indices are negative, then
+ // the mouse is not in a crystal and the selection should
+ // be cleared.
+ boolean validCrystal = (crystal != null);
+
+ // Get the currently selected calorimeter crystal.
+ Point curCrystal = ecalPanel.getSelectedCrystal();
+
+ // Perform event comparison checks.
+ boolean[] nullCrystal = { !validCrystal, curCrystal == null };
+ boolean[] disabledCrystal = { true, true };
+ if(!nullCrystal[0]) { disabledCrystal[0] = ecalPanel.isCrystalDisabled(crystal); }
+ if(!nullCrystal[1]) { disabledCrystal[1] = ecalPanel.isCrystalDisabled(curCrystal); }
+ boolean sameCrystal = true;
+ if(validCrystal) { sameCrystal = crystal.equals(curCrystal); }
+
+ // If the crystals are the same, there are no events to throw.
+ if(!sameCrystal) {
+ // If the new crystal is non-null and enabled, throw an event.
+ if(!nullCrystal[0] && !disabledCrystal[0]) { throwActivationEvent(crystal); }
+
+ // If the old crystal is non-null and enabled, throw an event.
+ if(!nullCrystal[1] && !disabledCrystal[1]) { throwDeactivationEvent(curCrystal); }
+ }
+
+ // If the crystal is valid, then set the selected crystal
+ // to the current one.
+ if(validCrystal) { ecalPanel.setSelectedCrystal(crystal); }
+
+ // Otherwise, clear the selection.
+ else { ecalPanel.clearSelectedCrystal(); }
+
+ // Update the status panel.
+ updateStatusPanel();
+ }
+
+ /**
+ * Triggers crystal activation events on all listeners for
+ * this component.
+ * @param activatedCrystal - The panel coordinates for the
+ * activated crystal.
+ */
+ private void throwActivationEvent(Point activatedCrystal) {
+ // Create a crystal event.
+ CrystalEvent ce = new CrystalEvent(Viewer.this, activatedCrystal);
+
+ // Throw the event with every listener.
+ for(CrystalListener cl : listenerList) { cl.crystalActivated(ce); }
+ }
+
+ /**
+ * Triggers crystal deactivation events on all listeners for
+ * this component.
+ * @param deactivatedCrystal - The panel coordinates for the
+ * deactivated crystal.
+ */
+ private void throwDeactivationEvent(Point deactivatedCrystal) {
+ // Create a crystal event.
+ CrystalEvent ce = new CrystalEvent(Viewer.this, deactivatedCrystal);
+
+ // Throw the event with every listener.
+ for(CrystalListener cl : listenerList) { cl.crystalDeactivated(ce); }
+ }
}
/**
Added: java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/util/CrystalDataSet.java
=============================================================================
--- java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/util/CrystalDataSet.java (added)
+++ java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/util/CrystalDataSet.java Sat Nov 1 02:29:56 2014
@@ -0,0 +1,213 @@
+package org.hps.monitoring.ecal.eventdisplay.util;
+
+import java.awt.Point;
+
+/**
+ * Class <code>CrystalDataSet</code> contains all of the hardware data
+ * for a single calorimeter crystal as defined in the crystal hardware
+ * reference sheet.
+ *
+ * @author Kyle McCarty
+ */
+public class CrystalDataSet {
+ // Data points.
+ private final Point crystalIndex;
+ private final short apd;
+ private final PreamplifierNumber preamp;
+ private final short ledChannel;
+ private final byte[] ledDriver;
+ private final byte fadcSlot;
+ private final byte fadcChannel;
+ private final byte splitterNum;
+ private final byte hvGroup;
+ private final byte jout;
+ private final String mb;
+ private final short channel;
+ private final int gain;
+
+ /**
+ * Defines the data set.
+ * @param ix - The crystal's x-index in the LCSimcoordinate system.
+ * @param iy - The crystal's y-index in the LCSimcoordinate system.
+ * @param apd - The number of the APD attached to the crystal.
+ * @param preamp - The number of the crystal's premaplifier. This
+ * may also include a reference wire color.
+ * @param ledChannel - The channel number for the crystal's LED.
+ * @param ledDriver
+ * @param fadcSlot - The FADC slot the crystal occupies.
+ * @param fadcChannel - The channel number through which the crystal
+ * communicates with the FADC.
+ * @param splitter
+ * @param hvGroup - The high voltage group for which the crystal
+ * is a member.
+ * @param jout
+ * @param mb
+ * @param channel
+ * @param gain - The crystal's gain.
+ */
+ public CrystalDataSet(int ix, int iy, int apd, String preamp, int ledChannel,
+ double ledDriver, int fadcSlot, int fadcChannel, int splitter, int hvGroup,
+ int jout, String mb, int channel, int gain) {
+ // Define crystal indices.
+ crystalIndex = new Point(ix, iy);
+
+ // Define the general properties.
+ this.apd = (short) apd;
+ this.ledChannel = (short) ledChannel;
+ this.fadcSlot = (byte) fadcSlot;
+ this.fadcChannel = (byte) fadcChannel;
+ this.splitterNum = (byte) splitter;
+ this.hvGroup = (byte) hvGroup;
+ this.jout = (byte) jout;
+ this.channel = (short) channel;
+ this.gain = gain;
+ this.mb = mb;
+
+ // Define the LED driver.
+ this.ledDriver = new byte[2];
+ this.ledDriver[0] = (byte) Math.floor(ledDriver);
+ this.ledDriver[1] = (byte) ((ledDriver - this.ledDriver[0]) * 10);
+
+ // Handle the preamplifier number.
+ StringBuffer num = new StringBuffer();
+ StringBuffer col = new StringBuffer();
+ for(char c : preamp.toCharArray()) {
+ if(Character.isDigit(c)) { num.append(c); }
+ else { col.append(c); }
+ }
+ int number = Integer.parseInt(num.toString());
+ String color = null;
+ if(col.length() != 0) { color = col.toString(); }
+ this.preamp = new PreamplifierNumber(number, color);
+ }
+
+ /**
+ * Gets the crystal's positional indices in the LCSim coordinate
+ * system.
+ * @return Returns the crystal's positional indices as a <code>
+ * Point</code> object.
+ */
+ public Point getCrystalIndex() { return crystalIndex; }
+
+ /**
+ * Gets the crystal's x-index in the LCSim coordinate system.
+ * @return Returns the crystal's x-index as an <code>int</code>
+ * primitive.
+ */
+ public int getCrystalXIndex() { return crystalIndex.x; }
+
+ /**
+ * Gets the crystal's y-index in the LCSim coordinate system.
+ * @return Returns the crystal's y-index as an <code>int</code>
+ * primitive.
+ */
+ public int getCrystalYIndex() { return crystalIndex.y; }
+
+ /**
+ * Gets the number of the APD attached to the crystal.
+ * @return Returns the crystal's APD number as an <code>int</code>
+ * primitive.
+ */
+ public int getAPDNumber() { return apd; }
+
+ /**
+ * Gets the crystal's preamplifier reference data.
+ * @return Returns the preamplifier reference as a <code>
+ * PreamplifierNumber</code> object.
+ */
+ public PreamplifierNumber getPreamplifierNumber() { return preamp; }
+
+ /**
+ * Gets the crystal's LED channel.
+ * @return Returns the LED channel as an <code>int</code> primitive.
+ */
+ public int getLEDChannel() { return ledChannel; }
+
+ public double getLEDDriver() {
+ return ((double) ledDriver[0]) + ((double) ledDriver[1] / 10);
+ }
+
+ /**
+ * Gets the crystal's FADC slot.
+ * @return Returns the FADC slot as an <code>int</code> primitive.
+ */
+ public int getFADCSlot() { return fadcSlot; }
+
+ /**
+ * Gets the crystal's FADC channel.
+ * @return Returns the FADC channel as an <code>int</code> primitive.
+ */
+ public int getFADCChannel() { return fadcChannel; }
+
+ public int getSplitterNumber() { return splitterNum; }
+
+ /**
+ * Gets the crystal's high voltage group.
+ * @return Returns the high voltage group number as an <code>int
+ * </code> primitive.
+ */
+ public int getHighVoltageGroup() { return hvGroup; }
+
+ public int getJout() { return jout; }
+
+ public String getMB() { return mb; }
+
+ public int getChannel() { return channel; }
+
+ /**
+ * Gets the crystal's gain.
+ * @return Returns the gain as an <code>int</code> primitive.
+ */
+ public int getGain() { return gain; }
+
+ /**
+ * Class <code>PreamplifierNumber</code> represents the number
+ * of a crystal's preamplifier. It can also contain a reference
+ * wire color if necessary.
+ *
+ * @author Kyle McCarty
+ */
+ public class PreamplifierNumber {
+ private final short number;
+ private final String color;
+
+ /**
+ * Initializes a preamplifier number with no reference wire
+ * color.
+ * @param number - The preamplifier's number.
+ */
+ public PreamplifierNumber(int number) { this(number, null); }
+
+ /**
+ * Initializes a preamplifier number with the specified reference
+ * wire color.
+ * @param number - The preamplifier's number.
+ * @param color - The reference wire color.
+ */
+ public PreamplifierNumber(int number, String color) {
+ this.number = (short) number;
+ this.color = color;
+ }
+
+ /**
+ * Gets the number of the preamplifier.
+ * @return Returns the preamplifier number as an <code>int
+ * </code> primitive.
+ */
+ public int getNumber() { return number; }
+
+ /**
+ * Gets the reference wire color associated with the crystal's
+ * preamplifier if it exists.
+ * @return Returns the reference wire color as a <code>String
+ * </code> object or <code>null</code> if it does not exist.
+ */
+ public String getColor() { return color; }
+
+ @Override
+ public String toString() {
+ if(color == null) { return "" + number; }
+ else { return number + " (" + color + ")"; }
+ }
+ }
+}
Added: java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/util/EcalWiringManager.java
=============================================================================
--- java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/util/EcalWiringManager.java (added)
+++ java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/util/EcalWiringManager.java Sat Nov 1 02:29:56 2014
@@ -0,0 +1,112 @@
+package org.hps.monitoring.ecal.eventdisplay.util;
+
+import java.awt.Point;
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Scanner;
+
+/**
+ * Class <code>EcalWiringManager</code> reads in the crystal hardware
+ * data sheet for the calorimeter and stores the data in <code>
+ * CrystalDataSet</code> objects for access and reference by the <code>
+ * Viewer</code> classes. Crystal LCSim indices are mapped to the data
+ * set that corresponds to that crystal.
+ *
+ * @author Kyle McCarty
+ */
+public class EcalWiringManager {
+ // Delimiter class statics.
+ public static final int SPACE_DELIMITED = 1;
+ public static final int TAB_DELIMITED = 2;
+ public static final int COMMA_DELIMITED = 3;
+
+ // Internal variables.
+ private Map<Point, CrystalDataSet> crystalMap = new HashMap<Point, CrystalDataSet>(442);
+
+ /**
+ * Initializes an <code>EcalWiringManager</code> database with
+ * hardware information loaded from the indicated file. The data
+ * file is assumed to be comma delimited and the first line is
+ * assumed to be a header line and to not contain data.
+ * @param dataFile - The path to the data file.
+ * @throws IOException Occurs if there is an error opening or parsing
+ * the data file.
+ */
+ public EcalWiringManager(String dataFile) throws IOException {
+ this(dataFile, COMMA_DELIMITED, true);
+ }
+
+ /**
+ * Initializes an <code>EcalWiringManager</code> database with
+ * hardware information loaded from the indicated file.
+ * @param dataFile - The path to the data file.
+ * @param delimiter - The delimiter used by the data file.
+ * @param skipFirstLine - Whether the first line should be skipped.
+ * @throws IOException Occurs if there is an error opening or parsing
+ * the data file.
+ */
+ public EcalWiringManager(String dataFile, int delimiter, boolean skipFirstLine) throws IOException {
+ // Create a file reader.
+ FileReader baseReader = new FileReader(dataFile);
+ BufferedReader reader = new BufferedReader(baseReader);
+
+ // If the first line should be skipped, do that.
+ if(skipFirstLine) { reader.readLine(); }
+
+ // Iterate over the lines of the data file.
+ String curLine = null;
+ readLoop:
+ while((curLine = reader.readLine()) != null) {
+ // If the current line is empty, skip it.
+ if(curLine.isEmpty()) { continue readLoop; }
+
+ // Create a line scanner.
+ Scanner lineScan = new Scanner(curLine);
+ if(delimiter == COMMA_DELIMITED) { lineScan.useDelimiter(","); }
+ else if(delimiter == SPACE_DELIMITED) { lineScan.useDelimiter(" *"); }
+ else if(delimiter == TAB_DELIMITED) { lineScan.useDelimiter("\t"); }
+
+ // Get the crystal data values.
+ int ix = lineScan.nextInt();
+ int iy = lineScan.nextInt();
+ int apd = lineScan.nextInt();
+ String preamp = lineScan.next();
+ int ledChan = lineScan.nextInt();
+ double ledDriver = lineScan.nextDouble();
+ int fadcSlot = lineScan.nextInt();
+ int fadcChan = lineScan.nextInt();
+ int splitter = lineScan.nextInt();
+ int hvGroup = lineScan.nextInt();
+ int jout = lineScan.nextInt();
+ String mb = lineScan.next();
+ int channel = lineScan.nextInt();
+ int gain = lineScan.nextInt();
+ lineScan.close();
+
+ // Create a crystal data set in which to store the data.
+ CrystalDataSet cds = new CrystalDataSet(ix, iy, apd, preamp, ledChan, ledDriver, fadcSlot,
+ fadcChan, splitter, hvGroup, jout, mb, channel, gain);
+
+ // Map the crystal index to the crystal data set.
+ crystalMap.put(cds.getCrystalIndex(), cds);
+ }
+
+ // Close the readers.
+ reader.close();
+ baseReader.close();
+ }
+
+ /**
+ * Gets the set of calorimeter hardware data associated with the
+ * crystal at the given index.
+ * @param crystalIndex - The index of the crystal for which to obtain
+ * the hardware information. This should be in LCSim coordinates.
+ * @return Returns the hardware information for the crystal as a
+ * <code>CrystalDataSet</code> object or returns <code>null</code>
+ * if the crystal index is invalid.
+ */
+ public CrystalDataSet getCrystalData(Point crystalIndex) { return crystalMap.get(crystalIndex); }
+}
|