Author: mccaky
Date: Mon Nov 3 11:46:24 2014
New Revision: 1425
Log:
Added calorimeter filter panel code. Not currently accessible.
Added:
java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/CrystalFilterPanel.java (with props)
java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/util/MapValueIterator.java (with props)
Modified:
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/PDataEventViewer.java
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/EcalWiringManager.java
Added: java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/CrystalFilterPanel.java
=============================================================================
--- java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/CrystalFilterPanel.java (added)
+++ java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/CrystalFilterPanel.java Mon Nov 3 11:46:24 2014
@@ -0,0 +1,889 @@
+package org.hps.monitoring.ecal.eventdisplay.ui;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.Point;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.SpringLayout;
+
+import org.hps.monitoring.ecal.eventdisplay.util.CrystalDataSet;
+import org.hps.monitoring.ecal.eventdisplay.util.CrystalDataSet.Motherboard;
+import org.hps.monitoring.ecal.eventdisplay.util.CrystalDataSet.Preamplifier;
+import org.hps.monitoring.ecal.eventdisplay.util.EcalWiringManager;
+
+/**
+ * Class <code>CrystalFilterPanel</code> is an extension of <code>
+ * JPanel</code> that allows users to select filters for crystals from
+ * the properties stored in a <code>CrystalDataSet</code> object and
+ * filter all the crystals present in an <code>EcalWiringManager</code>
+ * object by said properties.<br/>
+ * <br/>
+ * <code>CrystalFilterPanel</code> alerts other classes that a filter
+ * has been applied through <code>ActionListener</code> objects.
+ *
+ * @author Kyle McCarty
+ * @see JPanel
+ * @see CrystalDataSet
+ * @see EcalWiringManager
+ */
+public final class CrystalFilterPanel extends JPanel {
+ // Internal variables.
+ private Dimension preferredSize = null;
+ private final EcalWiringManager manager;
+ private List<Point> filteredList = null;
+ private static final long serialVersionUID = 1L;
+ private CDSComparator cdsCompare = new CDSComparator();
+ private List<ActionListener> alList = new ArrayList<ActionListener>();
+ public static final int EVENT_FILTER_APPLIED = ActionEvent.RESERVED_ID_MAX + 10;
+ public static final int EVENT_FILTER_REMOVED = ActionEvent.RESERVED_ID_MAX + 11;
+
+ // Component variables.
+ private JCheckBox[] checkActive;
+ private JComboBox<?>[] comboField;
+ private JButton buttonApply;
+ private JButton buttonRemove;
+ private JButton buttonClear;
+ private JTextArea textStatus;
+
+ // Component index references and related statics.
+ private static final int INDEX_X = 0;
+ private static final int INDEX_Y = 1;
+ private static final int INDEX_APD = 2;
+ private static final int INDEX_PREAMP = 3;
+ private static final int INDEX_LED_CHANNEL = 4;
+ private static final int INDEX_LED_DRIVER = 5;
+ private static final int INDEX_FADC_SLOT = 6;
+ private static final int INDEX_FADC_CHANNEL = 7;
+ private static final int INDEX_SPLITTER = 8;
+ private static final int INDEX_HV_GROUP = 9;
+ private static final int INDEX_JOUT = 10;
+ private static final int INDEX_MOTHERBOARD = 11;
+ private static final int INDEX_CHANNEL = 12;
+ private static final int INDEX_GAIN = 13;
+ private static final int INDICES = 14;
+ private static final Color COLOR_CHECK_FONT_ACTIVE = Color.BLACK;
+ private static final Color COLOR_CHECK_FONT_INACTIVE = Color.GRAY;
+ private static final String[] FIELD_NAME = { "x-Index", "y-Index", "APD Number",
+ "Preamp Number", "LED Channel", "LED Driver", "FADC Slot", "FADC Channel",
+ "Splitter Number", "H.V. Group", "Jout", "Motherboard", "Channel", "Gain" };
+
+ // Spacing constants.
+ private static final int hexternal = 15;
+ private static final int vexternal = 15;
+ private static final int hinternal = 10;
+ private static final int vinternal = 5;
+
+ public CrystalFilterPanel(EcalWiringManager dataManager) {
+ // Store the manager.
+ manager = dataManager;
+
+ // Create the panel layout.
+ SpringLayout layout = new SpringLayout();
+ setLayout(layout);
+
+ // Instantiate the check boxes.
+ JCheckBox largestCheck = null;
+ checkActive = new JCheckBox[INDICES];
+ for(int index = 0; index < INDICES; index++) {
+ // Instantiate the check box.
+ checkActive[index] = new JCheckBox(FIELD_NAME[index]);
+ checkActive[index].setSelected(false);
+ checkActive[index].setForeground(COLOR_CHECK_FONT_INACTIVE);
+ checkActive[index].addItemListener(new CheckListener(index));
+ add(checkActive[index]);
+
+ // Get the largest check box.
+ if(largestCheck == null) { largestCheck = checkActive[index]; }
+ else {
+ if(largestCheck.getPreferredSize().width < checkActive[index].getPreferredSize().width) {
+ largestCheck = checkActive[index];
+ }
+ }
+ }
+
+ // Create sets to store all possible entries for each crystal
+ // data field.
+ Set<Integer> xIndexSet = new HashSet<Integer>();
+ Set<Integer> yIndexSet = new HashSet<Integer>();
+ Set<Integer> apdSet = new HashSet<Integer>();
+ Set<Preamplifier> preampSet = new HashSet<Preamplifier>();
+ Set<Integer> ledChannelSet = new HashSet<Integer>();
+ Set<Double> ledDriverSet = new HashSet<Double>();
+ Set<Integer> fadcSlotSet = new HashSet<Integer>();
+ Set<Integer> fadcChannelSet = new HashSet<Integer>();
+ Set<Integer> splitterSet = new HashSet<Integer>();
+ Set<Integer> hvGroupSet = new HashSet<Integer>();
+ Set<Integer> joutSet = new HashSet<Integer>();
+ Set<Integer> channelSet = new HashSet<Integer>();
+ Set<Integer> gainSet = new HashSet<Integer>();
+
+ // Iterate over all crystal data fields to obtain the set of
+ // all possible entries.
+ for(CrystalDataSet cds : manager) {
+ xIndexSet.add(cds.getCrystalXIndex());
+ yIndexSet.add(cds.getCrystalYIndex());
+ apdSet.add(cds.getAPDNumber());
+ preampSet.add(cds.getPreamplifierNumber());
+ ledChannelSet.add(cds.getLEDChannel());
+ ledDriverSet.add(cds.getLEDDriver());
+ fadcSlotSet.add(cds.getFADCSlot());
+ fadcChannelSet.add(cds.getFADCChannel());
+ splitterSet.add(cds.getSplitterNumber());
+ hvGroupSet.add(cds.getHighVoltageGroup());
+ joutSet.add(cds.getJout());
+ channelSet.add(cds.getChannel());
+ gainSet.add(cds.getGain());
+ }
+
+ // Dump all of the set data into a list for each field.
+ Integer[] xIndex = xIndexSet.toArray(new Integer[xIndexSet.size()]);
+ Integer[] yIndex = yIndexSet.toArray(new Integer[yIndexSet.size()]);
+ Integer[] apd = apdSet.toArray(new Integer[apdSet.size()]);
+ Preamplifier[] preamp = preampSet.toArray(new Preamplifier[preampSet.size()]);
+ Integer[] ledChannel = ledChannelSet.toArray(new Integer[ledChannelSet.size()]);
+ Double[] ledDriver = ledDriverSet.toArray(new Double[ledDriverSet.size()]);
+ Integer[] fadcSlot = fadcSlotSet.toArray(new Integer[fadcSlotSet.size()]);
+ Integer[] fadcChannel = fadcChannelSet.toArray(new Integer[fadcChannelSet.size()]);
+ Integer[] splitter = splitterSet.toArray(new Integer[splitterSet.size()]);
+ Integer[] hvGroup = hvGroupSet.toArray(new Integer[hvGroupSet.size()]);
+ Integer[] jout = joutSet.toArray(new Integer[joutSet.size()]);
+ Integer[] channel = channelSet.toArray(new Integer[channelSet.size()]);
+ Integer[] gain = gainSet.toArray(new Integer[gainSet.size()]);
+
+ // Generate the list of entries for the motherboard spinner.
+ //String[] motherboard = { "Top", "Bottom", "Left", "Right", "Top-Left", "Top-Right",
+ // "Bottom-Left", "Bottom-Right" };
+
+ // Sort all the lists in their natural order.
+ Arrays.sort(xIndex);
+ Arrays.sort(yIndex);
+ Arrays.sort(apd);
+ Arrays.sort(preamp);
+ Arrays.sort(ledChannel);
+ Arrays.sort(ledDriver);
+ Arrays.sort(fadcSlot);
+ Arrays.sort(fadcChannel);
+ Arrays.sort(splitter);
+ Arrays.sort(hvGroup);
+ Arrays.sort(jout);
+ //Arrays.sort(motherboard);
+ Arrays.sort(channel);
+ Arrays.sort(gain);
+
+ // Instantiate each of the field combo boxes.
+ comboField = new JComboBox[INDICES];
+ comboField[INDEX_X] = new JComboBox<Integer>(xIndex);
+ comboField[INDEX_Y] = new JComboBox<Integer>(yIndex);
+ comboField[INDEX_APD] = new JComboBox<Integer>(apd);
+ comboField[INDEX_PREAMP] = new JComboBox<Preamplifier>(preamp);
+ comboField[INDEX_LED_CHANNEL] = new JComboBox<Integer>(ledChannel);
+ comboField[INDEX_LED_DRIVER] = new JComboBox<Double>(ledDriver);
+ comboField[INDEX_FADC_SLOT] = new JComboBox<Integer>(fadcSlot);
+ comboField[INDEX_FADC_CHANNEL] = new JComboBox<Integer>(fadcChannel);
+ comboField[INDEX_SPLITTER] = new JComboBox<Integer>(splitter);
+ comboField[INDEX_HV_GROUP] = new JComboBox<Integer>(hvGroup);
+ comboField[INDEX_JOUT] = new JComboBox<Integer>(jout);
+ comboField[INDEX_MOTHERBOARD] = new JComboBox<Position>(Position.values());
+ comboField[INDEX_CHANNEL] = new JComboBox<Integer>(channel);
+ comboField[INDEX_GAIN] = new JComboBox<Integer>(gain);
+
+ // Set the properties of the combo boxes.
+ for(JComboBox<?> combo : comboField) {
+ combo.setEnabled(false);
+ combo.setEditable(false);
+ add(combo);
+ }
+
+ // Instantiate and set the properties of the apply button.
+ buttonApply = new JButton("Apply Filter");
+ buttonApply.setToolTipText("Highlight all crystals that match the selected filter.");
+ buttonApply.setEnabled(false);
+ add(buttonApply);
+ buttonApply.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ // Apply the active filter.
+ applyFilter();
+
+ // Enable the remove filter button.
+ buttonRemove.setEnabled(true);
+ }
+ });
+
+ // Instantiate and set the properties of the remove button.
+ buttonRemove = new JButton("Remove Filter");
+ buttonRemove.setToolTipText("Clear all filter-related crystal highlighting.");
+ buttonRemove.setEnabled(false);
+ add(buttonRemove);
+ buttonRemove.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ // Remove the list of filtered crystals.
+ removeFilter();
+
+ // Disable the remove filter button.
+ buttonRemove.setEnabled(false);
+ }
+ });
+
+ // Instantiate and set the properties of the remove button.
+ buttonClear = new JButton("Clear Filters");
+ buttonClear.setToolTipText("Reset all filters to the default and disable them.");
+ add(buttonClear);
+ buttonClear.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ // Remove the list of filtered crystals.
+ removeFilter();
+
+ // Disable all of the filter check boxes.
+ for(JCheckBox check : checkActive) {
+ check.setSelected(false);
+ }
+
+ // Set the selected filter value for each filter to
+ // the original value.
+ for(JComboBox<?> combo : comboField) {
+ combo.setSelectedIndex(0);
+ }
+ }
+ });
+
+ // Instantiate the filter status text area.
+ textStatus = new JTextArea();
+ textStatus.setEditable(false);
+ textStatus.setText("Active Filters: None");
+ textStatus.setFont(new Font(Font.MONOSPACED, getFont().getStyle(), getFont().getSize()));
+ JScrollPane textScroller = new JScrollPane(textStatus);
+ add(textScroller);
+
+ // Determine if the check boxes or the spinners have a larger
+ // preferred height.
+ boolean checkLarger = true;
+ if(checkActive[INDEX_X].getPreferredSize().height < comboField[INDEX_X].getPreferredSize().height) {
+ checkLarger = false;
+ }
+
+ // Place the filter components onto the layout.
+ for(int index = 0; index < INDICES; index++) {
+ // The first component needs to use the top of the panel
+ // for its upper border.
+ if(index == 0) {
+ layout.putConstraint(SpringLayout.NORTH, checkActive[index], vexternal, SpringLayout.NORTH, this);
+ layout.putConstraint(SpringLayout.NORTH, comboField[index], vexternal, SpringLayout.NORTH, this);
+ }
+ // Subsequent panels are locked to the previous entry's
+ // lower border.
+ else {
+ if(checkLarger) {
+ layout.putConstraint(SpringLayout.NORTH, checkActive[index], vinternal, SpringLayout.SOUTH, checkActive[index - 1]);
+ layout.putConstraint(SpringLayout.NORTH, comboField[index], vinternal, SpringLayout.SOUTH, checkActive[index - 1]);
+ }
+ else {
+ layout.putConstraint(SpringLayout.NORTH, checkActive[index], vinternal, SpringLayout.SOUTH, comboField[index - 1]);
+ layout.putConstraint(SpringLayout.NORTH, comboField[index], vinternal, SpringLayout.SOUTH, comboField[index - 1]);
+ }
+ }
+
+ // All check boxes have left borders locked to the left side
+ // of the panel. All spinners have left borders locked to
+ // the right border of the widest check box. Finally, all of
+ // the spinners have right borders locked the right side of
+ // the panel.
+ layout.putConstraint(SpringLayout.WEST, checkActive[index], hexternal, SpringLayout.WEST, this);
+ layout.putConstraint(SpringLayout.WEST, comboField[index], hinternal, SpringLayout.EAST, largestCheck);
+ layout.putConstraint(SpringLayout.EAST, comboField[index], -hexternal, SpringLayout.EAST, this);
+ }
+
+ // Place the status text area.
+ JComponent previous = comboField[INDICES - 1];
+ if(checkLarger) { previous = checkActive[INDICES - 1]; }
+ layout.putConstraint(SpringLayout.NORTH, textScroller, vexternal, SpringLayout.SOUTH, previous);
+ layout.putConstraint(SpringLayout.WEST, textScroller, hexternal, SpringLayout.WEST, this);
+ layout.putConstraint(SpringLayout.EAST, textScroller, -hexternal, SpringLayout.EAST, this);
+ layout.putConstraint(SpringLayout.SOUTH, textScroller, -hexternal, SpringLayout.NORTH, buttonApply);
+
+ // Place the command buttons onto the layout.
+ layout.putConstraint(SpringLayout.SOUTH, buttonApply, -vexternal, SpringLayout.SOUTH, this);
+ layout.putConstraint(SpringLayout.WEST, buttonApply, hexternal, SpringLayout.WEST, this);
+ layout.putConstraint(SpringLayout.SOUTH, buttonRemove, -vexternal, SpringLayout.SOUTH, this);
+ layout.putConstraint(SpringLayout.WEST, buttonRemove, hinternal, SpringLayout.EAST, buttonApply);
+ layout.putConstraint(SpringLayout.SOUTH, buttonClear, -vexternal, SpringLayout.SOUTH, this);
+ layout.putConstraint(SpringLayout.WEST, buttonClear, hinternal, SpringLayout.EAST, buttonRemove);
+ }
+
+ /**
+ * Adds an <code>ActionListener</code> object to this component.
+ * @param listener - The listener to add.
+ */
+ public void addActionListener(ActionListener listener) {
+ if(listener != null) { alList.add(listener); }
+ }
+
+ /**
+ * Gets the list of <code>ActionListener</code> objects attached to
+ * this component.
+ * @return Returns the listeners as an array of <code>ActionListener
+ * </code> objects.
+ */
+ public ActionListener[] getActionListeners() {
+ return alList.toArray(new ActionListener[alList.size()]);
+ }
+
+ /**
+ * Gets the list of crystals that pass the applied filter.
+ * @return Returns a <code>List</code> collection of <code>Point
+ * </code> objects representing the LCSim coordinates of every
+ * crystal that passes the applied filter. If no filter is active,
+ * returns <code>null</code>.
+ */
+ public List<Point> getFilteredCrystals() { return filteredList; }
+
+ @Override
+ public Dimension getPreferredSize() {
+ // If there is a user defined preferred size, use that.
+ if(preferredSize != null) { return preferredSize; }
+
+ // Track the minimum size needed to display the panel.
+ int preferredHeight = 4 * vexternal;
+
+ // Determine if the combo boxes or check boxes are larger.
+ int checkHeight = checkActive[INDEX_X].getPreferredSize().height;
+ int comboHeight = comboField[INDEX_X].getPreferredSize().height;
+ boolean checkLarger = checkHeight > comboHeight;
+ int compHeight = checkLarger ? checkHeight : comboHeight;
+
+ // Get the preferred height of the filters.
+ preferredHeight += (INDICES - 1) * (vinternal + compHeight);
+
+ // Add the button preferred height.
+ preferredHeight += buttonApply.getPreferredSize().height;
+
+ // Add 50 for the text area.
+ preferredHeight += 150;
+
+ // The preferred width is the width needed by the buttons.
+ int preferredWidth = hexternal + hexternal + hinternal + hinternal;
+ preferredWidth += buttonApply.getPreferredSize().width;
+ preferredWidth += buttonRemove.getPreferredSize().width;
+ preferredWidth += buttonClear.getPreferredSize().width;
+
+ // Return the result.
+ return new Dimension(preferredWidth, preferredHeight);
+ }
+
+ /**
+ * Indicates whether or not a filter is currently applied.
+ * @return Returns <code>true</code> if there is an active filter
+ * and <code>false</code> if there is not.
+ */
+ public boolean isActive() { return filteredList != null; }
+
+ /**
+ * Removes the indicated <code>ActionListener</code> object from
+ * this component if it exists.
+ * @param listener - The listener to remove.
+ */
+ public void removeActionListener(ActionListener listener) {
+ alList.remove(listener);
+ }
+
+ @Override
+ public void setPreferredSize(Dimension preferredSize) {
+ this.preferredSize = preferredSize;
+ }
+
+ /**
+ * Applies the filter defined by the currently selected filter
+ * options. If no filter options are selected, this does nothing.
+ */
+ private void applyFilter() {
+ // Make sure that at least one filter option is selected.
+ boolean isEnabled = false;
+ activeLoop:
+ for(JCheckBox check : checkActive) {
+ if(check.isEnabled()) {
+ isEnabled = true;
+ break activeLoop;
+ }
+ }
+ if(!isEnabled) { return; }
+
+ // Clear the filter parameters.
+ cdsCompare.clearFilters();
+
+ // Store the textual form of the active filters.
+ StringBuffer filterBuffer = new StringBuffer("Active Filters:\n");
+
+ // Set the filter parameters.
+ if(checkActive[INDEX_X].isSelected()) {
+ int val = (Integer) comboField[INDEX_X].getSelectedItem();
+ cdsCompare.addXIndexFilter(val);
+ filterBuffer.append(String.format(" %-20s :: %d%n", "x-Index", val));
+ }
+ if(checkActive[INDEX_Y].isSelected()) {
+ int val = (Integer) comboField[INDEX_Y].getSelectedItem();
+ cdsCompare.addYIndexFilter(val);
+ filterBuffer.append(String.format(" %-20s :: %d%n", "y-Index", val));
+ }
+ if(checkActive[INDEX_APD].isSelected()) {
+ int val = (Integer) comboField[INDEX_APD].getSelectedItem();
+ cdsCompare.addAPDFilter(val);
+ filterBuffer.append(String.format(" %-20s :: %d%n", "APD Number", val));
+ }
+ if(checkActive[INDEX_PREAMP].isSelected()) {
+ Preamplifier val = (Preamplifier) comboField[INDEX_PREAMP].getSelectedItem();
+ cdsCompare.addPreampFilter((Preamplifier) comboField[INDEX_PREAMP].getSelectedItem());
+ filterBuffer.append(String.format(" %-20s :: %s%n", "APD Number", val.toString()));
+ }
+ if(checkActive[INDEX_LED_CHANNEL].isSelected()) {
+ int val = (Integer) comboField[INDEX_LED_CHANNEL].getSelectedItem();
+ cdsCompare.addLEDChannelFilter(val);
+ filterBuffer.append(String.format(" %-20s :: %d%n", "LED Channel Number", val));
+ }
+ if(checkActive[INDEX_LED_DRIVER].isSelected()) {
+ double val = (Double) comboField[INDEX_LED_DRIVER].getSelectedItem();
+ cdsCompare.addLEDDriverFilter(val);
+ filterBuffer.append(String.format(" %-20s :: %.1f%n", "LED Driver", val));
+ }
+ if(checkActive[INDEX_FADC_SLOT].isSelected()) {
+ int val = (Integer) comboField[INDEX_FADC_SLOT].getSelectedItem();
+ cdsCompare.addFADCSlotFilter(val);
+ filterBuffer.append(String.format(" %-20s :: %d%n", "FADC Slot Number", val));
+ }
+ if(checkActive[INDEX_FADC_CHANNEL].isSelected()) {
+ int val = (Integer) comboField[INDEX_FADC_CHANNEL].getSelectedItem();
+ cdsCompare.addFADCChannelFilter(val);
+ filterBuffer.append(String.format(" %-20s :: %d%n", "FADC Channel Number", val));
+ }
+ if(checkActive[INDEX_SPLITTER].isSelected()) {
+ int val = (Integer) comboField[INDEX_SPLITTER].getSelectedItem();
+ cdsCompare.addSplitterFilter(val);
+ filterBuffer.append(String.format(" %-20s :: %d%n", "Splitter Number", val));
+ }
+ if(checkActive[INDEX_HV_GROUP].isSelected()) {
+ int val = (Integer) comboField[INDEX_HV_GROUP].getSelectedItem();
+ cdsCompare.addHVGroupFilter(val);
+ filterBuffer.append(String.format(" %-20s :: %d%n", "High Voltage Group", val));
+ }
+ if(checkActive[INDEX_JOUT].isSelected()) {
+ int val = (Integer) comboField[INDEX_JOUT].getSelectedItem();
+ cdsCompare.addJoutFilter(val);
+ filterBuffer.append(String.format(" %-20s :: %d%n", "Jout", val));
+ }
+ if(checkActive[INDEX_MOTHERBOARD].isSelected()) {
+ Position val = (Position) comboField[INDEX_MOTHERBOARD].getSelectedItem();
+ cdsCompare.addMotherboardFilter((Position) comboField[INDEX_MOTHERBOARD].getSelectedItem());
+ filterBuffer.append(String.format(" %-20s :: %s%n", "Motherboard Position", val.toString()));
+ }
+ if(checkActive[INDEX_CHANNEL].isSelected()) {
+ int val = (Integer) comboField[INDEX_CHANNEL].getSelectedItem();
+ cdsCompare.addChannelFilter(val);
+ filterBuffer.append(String.format(" %-20s :: %d%n", "Channel Number", val));
+ }
+ if(checkActive[INDEX_GAIN].isSelected()) {
+ int val = (Integer) comboField[INDEX_GAIN].getSelectedItem();
+ cdsCompare.addGainFilter(val);
+ filterBuffer.append(String.format(" %-20s :: %d%n", "Gain", val));
+ }
+
+ // Update the status pane.
+ textStatus.setText(filterBuffer.toString());
+
+ // Populate the filtered crystals list.
+ filteredList = new ArrayList<Point>();
+ for(CrystalDataSet cds : manager) {
+ if(cdsCompare.passesFilter(cds)) { filteredList.add(cds.getCrystalIndex()); }
+ }
+
+ // Throw an event to indicate that a filter was applied.
+ ActionEvent event = new ActionEvent(this, EVENT_FILTER_APPLIED, "Filter Applied");
+ for(ActionListener lst : alList) {
+ lst.actionPerformed(event);
+ }
+ }
+
+ /**
+ * Removes any active filters.
+ */
+ private void removeFilter() {
+ // Make sure that there is an active filter to remove.
+ if(filteredList == null) { return; }
+
+ // Clear the filter list.
+ filteredList = null;
+
+ // Update the status panel text.
+ textStatus.setText("Active Filters: None");
+
+ // Throw an event to indicate that a filter was removed.
+ ActionEvent event = new ActionEvent(this, EVENT_FILTER_REMOVED, "Filter Removed");
+ for(ActionListener lst : alList) {
+ lst.actionPerformed(event);
+ }
+ }
+
+ /**
+ * Enumerable <code>Position</code> specifies a location on the
+ * calorimeter.
+ *
+ * @author Kyle McCarty
+ */
+ private enum Position {
+ TOP(true, null), BOTTOM(false, null), LEFT(null, true), RIGHT(null, false),
+ TOP_LEFT(true, true), TOP_RIGHT(true, false), BOTTOM_LEFT(false, true), BOTTOM_RIGHT(false, false);
+
+ // Internal variables.
+ private String name = null;
+ private final Boolean isTop;
+ private final Boolean isLeft;
+
+ /**
+ * Instantiates a new position.
+ * @param isTop - <code>true</code> if the position is on the
+ * top and <code>false</code> if it is on the bottom. <code>
+ * null</code> indicates that it does not differentiate between
+ * this axis.
+ * @param isLeft - <code>true</code> if the position is on the
+ * left and <code>false</code> if it is on the right. <code>
+ * null</code> indicates that it does not differentiate between
+ * this axis.
+ */
+ private Position(Boolean isTop, Boolean isLeft) {
+ this.isTop = isTop;
+ this.isLeft = isLeft;
+ }
+
+ /**
+ * Checks whether a given motherboard position is consistent
+ * with the position enumerable.
+ * @param mb - The motherboard to check.
+ * @return Returns <code>true</code> if the motherboard position
+ * is consistent and <code>false</code> otherwise.
+ */
+ public boolean matchesPosition(Motherboard mb) {
+ // If this position needs to check top or bottom status,
+ // do so. Return false if it fails.
+ if(isTop != null && isTop != mb.isTop()) {
+ return false;
+ }
+
+ // If this position needs to check left or right status,
+ // do so. Return false if it fails.
+ if(isLeft != null && isLeft != mb.isLeft()) {
+ return false;
+ }
+
+ // If it passes all checks, return true.
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ // If the name has already been defined, return it.
+ if(name != null) { return name; }
+
+ // Otherwise, the name must be parsed from the system name.
+ // Create a string buffer to contain the parsed characters.
+ StringBuffer nameBuffer = new StringBuffer();
+
+ // Iterate over the characters in the name and process them.
+ boolean nextUpperCase = true;
+ for(char c : name().toCharArray()) {
+ if(c == '_') {
+ nameBuffer.append(' ');
+ nextUpperCase = true;
+ }
+ else if(nextUpperCase) {
+ nameBuffer.append(c);
+ nextUpperCase = false;
+ }
+ else { nameBuffer.append(Character.toLowerCase(c)); }
+ }
+
+ // Store the result.
+ name = nameBuffer.toString();
+
+ // Return the result.
+ return name;
+ }
+ }
+
+ /**
+ * Class <code>CheckListener</code> is an implementation of <code>
+ * ItemListener</code> that is linked to a specific component index
+ * and handles the enabling and disabling of filters.
+ *
+ * @author Kyle McCarty
+ * @see ItemListener
+ */
+ private class CheckListener implements ItemListener {
+ // Store the index of the components associated with the listener.
+ private final int index;
+
+ /**
+ * Instantiates a new <code>CheckListener</code> that is linked
+ * to the specified index.
+ * @param componentIndex - The index of the component.
+ */
+ public CheckListener(int componentIndex) { index = componentIndex; }
+
+ @Override
+ public void itemStateChanged(ItemEvent e) {
+ // Set the component properties according the selection
+ // status of the check box.
+ if(checkActive[index].isSelected()) {
+ checkActive[index].setForeground(COLOR_CHECK_FONT_ACTIVE);
+ comboField[index].setEnabled(true);
+ }
+ else {
+ checkActive[index].setForeground(COLOR_CHECK_FONT_INACTIVE);
+ comboField[index].setEnabled(false);
+ }
+
+ // If any of the filter check boxes are active, the active
+ // filter button should be clickable.
+ boolean active = false;
+ applyCheckLoop:
+ for(JCheckBox check : checkActive) {
+ if(check.isSelected()) {
+ active = true;
+ break applyCheckLoop;
+ }
+ }
+
+ // Set the apply button to the appropriate setting.
+ buttonApply.setEnabled(active);
+ }
+ }
+
+ /**
+ * Class <code>CDSComparator</code> allows a set of filters for
+ * each property in a <code>CrystalDataSet</code> to be defined.
+ * It then will check to see if a given <code>CrystalDataSet</code>
+ * object matches the <code>CDSComparator</code> properties.
+ *
+ * @author Kyle McCarty
+ */
+ private class CDSComparator {
+ // Filters.
+ private Integer filterX = null;
+ private Integer filterY = null;
+ private Integer filterAPD = null;
+ private Preamplifier filterPreamp = null;
+ private Integer filterLEDChannel = null;
+ private Double filterLEDDriver = null;
+ private Integer filterFADCSlot = null;
+ private Integer filterFADCChannel = null;
+ private Integer filterSplitter = null;
+ private Integer filterHVGroup = null;
+ private Integer filterJout = null;
+ private Position motherboard = null;
+ private Integer filterChannel = null;
+ private Integer filterGain = null;
+
+ /**
+ * Enables and sets the value of the x-index filter.
+ * @param xIndex - The filter value.
+ */
+ public void addXIndexFilter(int xIndex) { filterX = new Integer(xIndex); }
+
+ /**
+ * Enables and sets the value of the y-index filter.
+ * @param yIndex - The filter value.
+ */
+ public void addYIndexFilter(int yIndex) { filterY = new Integer(yIndex); }
+
+ /**
+ * Enables and sets the value of the APD number filter.
+ * @param apd - The filter value.
+ */
+ public void addAPDFilter(int apd) { filterAPD = new Integer(apd); }
+
+ /**
+ * Enables and sets the value of the preamplifier number filter.
+ * @param preamp - The filter value.
+ */
+ public void addPreampFilter(Preamplifier preamp) { filterPreamp = preamp; }
+
+ /**
+ * Enables and sets the value of the LED channel number filter.
+ * @param ledChannel - The filter value.
+ */
+ public void addLEDChannelFilter(int ledChannel) { filterLEDChannel = new Integer(ledChannel); }
+
+ /**
+ * Enables and sets the value of the LED driver filter.
+ * @param ledDriver - The filter value.
+ */
+ public void addLEDDriverFilter(double ledDriver) { filterLEDDriver = new Double(ledDriver); }
+
+ /**
+ * Enables and sets the value of the FADC slot filter.
+ * @param fadcSlot - The filter value.
+ */
+ public void addFADCSlotFilter(int fadcSlot) { filterFADCSlot = new Integer(fadcSlot); }
+
+ /**
+ * Enables and sets the value of the FADC channel filter.
+ * @param fadcChannel - The filter value.
+ */
+ public void addFADCChannelFilter(int fadcChannel) { filterFADCChannel = new Integer(fadcChannel); }
+
+ /**
+ * Enables and sets the value of the splitter number filter.
+ * @param splitterNum - The filter value.
+ */
+ public void addSplitterFilter(int splitterNum) { filterSplitter = new Integer(splitterNum); }
+
+ /**
+ * Enables and sets the value of the high voltage group filter.
+ * @param hvGroup - The filter value.
+ */
+ public void addHVGroupFilter(int hvGroup) { filterHVGroup = new Integer(hvGroup); }
+
+ /**
+ * Enables and sets the value of the Jout filter.
+ * @param jout - The filter value.
+ */
+ public void addJoutFilter(int jout) { filterJout = new Integer(jout); }
+
+ /**
+ * Enables and sets the value of the motherboard position filter.
+ * @param mb - The filter value.
+ */
+ public void addMotherboardFilter(Position mb) { motherboard = mb; }
+
+ /**
+ * Enables and sets the value of the channel number filter.
+ * @param channelNum - The filter value.
+ */
+ public void addChannelFilter(int channelNum) { filterChannel = new Integer(channelNum); }
+
+ /**
+ * Enables and sets the value of the gain filter.
+ * @param gain - The filter value.
+ */
+ public void addGainFilter(int gain) { filterGain = new Integer(gain); }
+
+ /**
+ * Resets all of the filters to the default disabled state.
+ */
+ public void clearFilters() {
+ filterX = null;
+ filterY = null;
+ filterAPD = null;
+ filterPreamp = null;
+ filterLEDChannel = null;
+ filterLEDDriver = null;
+ filterFADCSlot = null;
+ filterFADCChannel = null;
+ filterSplitter = null;
+ filterHVGroup = null;
+ filterJout = null;
+ motherboard = null;
+ filterChannel = null;
+ filterGain = null;
+ }
+
+ /**
+ * Checks to see if a given <code>CrystalDataSet</code> object
+ * matches all of the defined filter parameters.
+ * @param cds - The data set to check.
+ * @return Returns <code>true</code> if the <code>CrystalDataSet
+ * </code> matches the defined filter parameters and <code>false
+ * </code> otherwise.
+ */
+ public boolean passesFilter(CrystalDataSet cds) {
+ // Apply the filter for the crystal x-index.
+ if(filterX != null) {
+ if(cds.getCrystalXIndex() != filterX) { return false; }
+ }
+
+ // Apply the filter for the crystal y-index.
+ if(filterY != null) {
+ if(cds.getCrystalYIndex() != filterY) { return false; }
+ }
+
+ // Apply the filter for the crystal APD number.
+ if(filterAPD != null) {
+ if(cds.getAPDNumber() != filterAPD) { return false; }
+ }
+
+ // Apply the filter for the associated preamplifier.
+ if(filterPreamp != null) {
+ if(cds.getPreamplifierNumber() != filterPreamp) { return false; }
+ }
+
+ // Apply the filter for the crystal LED channel number.
+ if(filterLEDChannel != null) {
+ if(cds.getLEDChannel() != filterLEDChannel) { return false; }
+ }
+
+ // Apply the filter for the crystal LED driver.
+ if(filterLEDDriver != null) {
+ if(cds.getLEDDriver() != filterLEDDriver) { return false; }
+ }
+
+ // Apply the filter for the crystal FADC slot.
+ if(filterFADCSlot != null) {
+ if(cds.getFADCSlot() != filterFADCSlot) { return false; }
+ }
+
+ // Apply the filter for the crystal FADC channel.
+ if(filterFADCChannel != null) {
+ if(cds.getFADCChannel() != filterFADCChannel) { return false; }
+ }
+
+ // Apply the filter for the crystal splitter number.
+ if(filterSplitter != null) {
+ if(cds.getSplitterNumber() != filterSplitter) { return false; }
+ }
+
+ // Apply the filter for the crystal high voltage group.
+ if(filterHVGroup != null) {
+ if(cds.getHighVoltageGroup() != filterHVGroup) { return false; }
+ }
+
+ // Apply the filter for the Jout property.
+ if(filterJout != null) {
+ if(cds.getJout() != filterJout) { return false; }
+ }
+
+ // Apply the filter for the motherboard position.
+ if(motherboard != null) {
+ if(!motherboard.matchesPosition(cds.getMotherboard())) { return false; }
+ }
+
+ // Apply the filter for the crystal channel number.
+ if(filterChannel != null) {
+ if(cds.getChannel() != filterChannel) { return false; }
+ }
+
+ // Apply the filter for the crystal gain.
+ if(filterGain != null) {
+ if(cds.getGain() != filterGain) { return false; }
+ }
+
+ // If all filters succeeded, return true.
+ return true;
+ }
+ }
+}
Modified: 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 (original)
+++ java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/DataFileViewer.java Mon Nov 3 11:46:24 2014
@@ -1,7 +1,14 @@
package org.hps.monitoring.ecal.eventdisplay.ui;
import java.awt.Point;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
import java.io.IOException;
+import java.util.List;
+
+import javax.swing.JFrame;
import org.hps.monitoring.ecal.eventdisplay.io.EventManager;
import org.hps.monitoring.ecal.eventdisplay.util.CrystalDataSet;
@@ -40,6 +47,10 @@
private static final int FIELD_CHANNEL = 10;
private static final int FIELD_GAIN = 11;
+ // Filter panel components.
+ private JFrame filterWindow;
+ private CrystalFilterPanel filterPanel;
+
/**
* Initializes a new <code>DataFileViewer</code> that reads from
* the given event manager for event data and the given hardware
@@ -61,6 +72,48 @@
for(String fieldName : fieldNames) {
addStatusField(fieldName);
}
+
+ // Instantiate the crystal filter panel.
+ filterPanel = new CrystalFilterPanel(ewm);
+ filterWindow = new JFrame("Event Display Crystal Filter");
+ filterWindow.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
+ filterWindow.add(filterPanel);
+ filterWindow.pack();
+ filterWindow.setResizable(false);
+
+ // Add an action listener to note when the filter window applies
+ // a crystal filter.
+ filterPanel.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ // Clear the panel highlighting.
+ ecalPanel.clearHighlight();
+
+ // If the filter panel is active, highlight the crystals
+ // that passed the filter.
+ if(filterPanel.isActive()) {
+ // Get the list of filtered crystals.
+ List<Point> filterList = filterPanel.getFilteredCrystals();
+
+ // Highlight each of the filtered crystals.
+ for(Point crystal : filterList) {
+ ecalPanel.setCrystalHighlight(toPanelPoint(crystal), java.awt.Color.WHITE);
+ }
+ }
+ }
+ });
+
+ // Create a new key listener.
+ addKeyListener(new KeyAdapter() {
+ @Override
+ public void keyReleased(KeyEvent e) {
+ // Bring up the filter panel when 'f' is pressed.
+ if(e.getKeyCode() == 70) {
+ if(!filterWindow.isVisible()) { filterWindow.setVisible(true); }
+ else { filterWindow.setVisible(false); }
+ }
+ }
+ });
}
@Override
@@ -90,7 +143,7 @@
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_MB], "" + cds.getMotherboard().toString());
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/PDataEventViewer.java
=============================================================================
--- java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/PDataEventViewer.java (original)
+++ java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/PDataEventViewer.java Mon Nov 3 11:46:24 2014
@@ -89,7 +89,7 @@
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_MB], "" + cds.getMotherboard().toString());
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/util/CrystalDataSet.java
=============================================================================
--- java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/util/CrystalDataSet.java (original)
+++ java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/util/CrystalDataSet.java Mon Nov 3 11:46:24 2014
@@ -9,11 +9,11 @@
*
* @author Kyle McCarty
*/
-public class CrystalDataSet {
+public class CrystalDataSet {
// Data points.
private final Point crystalIndex;
private final short apd;
- private final PreamplifierNumber preamp;
+ private final Preamplifier preamp;
private final short ledChannel;
private final byte[] ledDriver;
private final byte fadcSlot;
@@ -21,7 +21,7 @@
private final byte splitterNum;
private final byte hvGroup;
private final byte jout;
- private final String mb;
+ private final Motherboard motherboard;
private final short channel;
private final int gain;
@@ -30,19 +30,20 @@
* @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
+ * @param preamp - The number of the crystal's preamplifier. 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 splitter - The number of the crystal's splitter.
* @param hvGroup - The high voltage group for which the crystal
* is a member.
- * @param jout
- * @param mb
- * @param channel
+ * @param jout - The crystal's signal channel group.
+ * @param mb - The position of the motherboard associated with the
+ * crystal.
+ * @param channel - The channel associated with the crystal.
* @param gain - The crystal's gain.
*/
public CrystalDataSet(int ix, int iy, int apd, String preamp, int ledChannel,
@@ -61,7 +62,7 @@
this.jout = (byte) jout;
this.channel = (short) channel;
this.gain = gain;
- this.mb = mb;
+ this.motherboard = Motherboard.getMotherboard(mb);
// Define the LED driver.
this.ledDriver = new byte[2];
@@ -78,7 +79,7 @@
int number = Integer.parseInt(num.toString());
String color = null;
if(col.length() != 0) { color = col.toString(); }
- this.preamp = new PreamplifierNumber(number, color);
+ this.preamp = new Preamplifier(number, color);
}
/**
@@ -115,7 +116,7 @@
* @return Returns the preamplifier reference as a <code>
* PreamplifierNumber</code> object.
*/
- public PreamplifierNumber getPreamplifierNumber() { return preamp; }
+ public Preamplifier getPreamplifierNumber() { return preamp; }
/**
* Gets the crystal's LED channel.
@@ -139,6 +140,11 @@
*/
public int getFADCChannel() { return fadcChannel; }
+ /**
+ * Gets the number of the splitter associated with the crystal.
+ * @return Returns the splitter number as an <code>int</code>
+ * primitive.
+ */
public int getSplitterNumber() { return splitterNum; }
/**
@@ -148,10 +154,25 @@
*/
public int getHighVoltageGroup() { return hvGroup; }
+ /**
+ * Gets the signal channel group for the crystal.
+ * @return Returns the signal channel group as an <code>int</code>
+ * primitive.
+ */
public int getJout() { return jout; }
- public String getMB() { return mb; }
-
+ /**
+ * Gets the positional information concerning the motherboard with
+ * which the crystal is associated.
+ * @return Returns the <code>Motherboard</code> enumerable attached
+ * to the crystal.
+ */
+ public Motherboard getMotherboard() { return motherboard; }
+
+ /**
+ * Gets the channel number associated with the crystal.
+ * @return Gets the channel number as an <code>int</code> primitive.
+ */
public int getChannel() { return channel; }
/**
@@ -161,30 +182,29 @@
public int getGain() { return gain; }
/**
- * Class <code>PreamplifierNumber</code> represents the number
+ * Class <code>Preamplifier</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 {
+ public class Preamplifier implements Comparable<Preamplifier> {
private final short number;
private final String color;
/**
- * Initializes a preamplifier number with no reference wire
- * color.
+ * Initializes a preamplifier 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
+ public Preamplifier(int number) { this(number, null); }
+
+ /**
+ * Initializes a preamplifier with the specified reference
* wire color.
* @param number - The preamplifier's number.
* @param color - The reference wire color.
*/
- public PreamplifierNumber(int number, String color) {
+ public Preamplifier(int number, String color) {
this.number = (short) number;
this.color = color;
}
@@ -209,5 +229,159 @@
if(color == null) { return "" + number; }
else { return number + " (" + color + ")"; }
}
+
+ @Override
+ public int compareTo(Preamplifier preamp) {
+ // Compare the preamplifier numbers.
+ int numCompare = Short.compare(number, preamp.number);
+
+ // If they are different, return this value.
+ if(numCompare != 0) { return numCompare; }
+
+ // The color string must now be compared. If both are null,
+ // then they are the same.
+ if(color == null && preamp.color == null) { return 0; }
+
+ // If one is null and the other is not, the null one is
+ // always ordered first.
+ if(color == null && preamp.color != null) { return -1; }
+ else if(color != null && preamp.color == null) { return 1; }
+
+ // If neither color is null, compare them traditionally.
+ return color.compareTo(preamp.color);
+ }
+ }
+
+ /**
+ * Enumerable <code>Motherboard</code> contains convenience methods
+ * for defining the motherboard location for a particular crystal.
+ *
+ * @author Kyle McCarty
+ */
+ public enum Motherboard {
+ /** The motherboard on the upper, left-hand side. */
+ TOP_LEFT(true, true),
+ /** The motherboard on the upper, right-hand side. */
+ TOP_RIGHT(true, false),
+ /** The motherboard on the lower, left-hand side. */
+ BOTTOM_LEFT(false, true),
+ /** The motherboard on the lower, right-hand side. */
+ BOTTOM_RIGHT(false, false);
+
+ private final boolean isTop;
+ private final boolean isLeft;
+
+ /**
+ * Instantiates a new motherboard enumerable.
+ * @param isTop - Indicates whether the motherboard is on the
+ * upper side of the detector.
+ * @param isLeft - Indicates whether the motherboard is on the
+ * left-hand side of the detector.
+ */
+ private Motherboard(boolean isTop, boolean isLeft) {
+ this.isTop = isTop;
+ this.isLeft = isLeft;
+ }
+
+ /**
+ * Indicates whether the motherboard is on the top of the
+ * detector or not.
+ * @return Returns <code>true</code> if the motherboard is on
+ * the upper half of the detector and <code>false</code> if it
+ * is not.
+ */
+ public boolean isTop() { return isTop; }
+
+ /**
+ * Indicates whether the motherboard is on the bottom of the
+ * detector or not.
+ * @return Returns <code>true</code> if the motherboard is on
+ * the lower half of the detector and <code>false</code> if it
+ * is not.
+ */
+ public boolean isBottom() { return !isTop; }
+
+ /**
+ * Indicates whether the motherboard is on the left-hand side
+ * of the detector or not.
+ * @return Returns <code>true</code> if the motherboard is on
+ * the left-hand side of the detector and <code>false</code>
+ * if it is not.
+ */
+ public boolean isLeft() { return isLeft; }
+
+ /**
+ * Indicates whether the motherboard is on the right-hand side
+ * of the detector or not.
+ * @return Returns <code>true</code> if the motherboard is on
+ * the right-hand side of the detector and <code>false</code>
+ * if it is not.
+ */
+ public boolean isRight() { return !isLeft; }
+
+ /**
+ * Gets the <code>Motherboard</code> enumerable associated
+ * with the given textual abbreviation. Valid arguments include
+ * "LT", "RT", "LB", and "RB".
+ * @param abbreviation - The textual abbreviation for the
+ * location of the motherboard.
+ * @return Returns the appropriate <code>Motherboard</code>
+ * enumerable if given a valid abbreviation and <code>null
+ * </code> otherwise.
+ */
+ public static final Motherboard getMotherboard(String abbreviation) {
+ // Abbreviations must be 2 characters in length.
+ if(abbreviation.length() != 2) { return null; }
+
+ // The first character must be either 'R' or 'L'.
+ boolean isLeft;
+ if(abbreviation.charAt(0) == 'L') { isLeft = true; }
+ else if(abbreviation.charAt(0) == 'R') { isLeft = false; }
+ else { return null; }
+
+ // The second character must be either 'T' or 'B'.
+ boolean isTop;
+ if(abbreviation.charAt(1) == 'T') { isTop = true; }
+ else if(abbreviation.charAt(1) == 'B') { isTop = false; }
+ else { return null; }
+
+ // Return the appropriate motherboard enumerable.
+ return getMotherboard(isTop, isLeft);
+ }
+
+ /**
+ * Gets the <code>Motherboard</code> enumerable associated
+ * with the given position.
+ * @param isTop - <code>true</code> indicates the motherboard
+ * on the top half of the detector and <code>false</code> the
+ * motherboard on the bottom half.
+ * @param isLeft - <code>true</code> indicates the motherboard
+ * on the left-hand side of the detector and <code>false</code>
+ * the motherboard on the right-hand side.
+ * @return Returns the appropriate <code>Motherboard</code>
+ * enumerable.
+ */
+ public static final Motherboard getMotherboard(boolean isTop, boolean isLeft) {
+ if(isTop) {
+ if(isLeft) { return TOP_LEFT; }
+ else { return TOP_RIGHT; }
+ }
+ else {
+ if(isLeft) { return BOTTOM_LEFT; }
+ else { return BOTTOM_RIGHT; }
+ }
+ }
+
+ @Override
+ public String toString() {
+ if(isTop) {
+ if(isLeft) { return "LT"; }
+ else { return "RT"; }
+ }
+ else {
+ if(isLeft) { return "LB"; }
+ else { return "RB"; }
+ }
+ }
}
}
Modified: 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 (original)
+++ java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/util/EcalWiringManager.java Mon Nov 3 11:46:24 2014
@@ -4,7 +4,11 @@
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Comparator;
import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import java.util.Scanner;
@@ -17,7 +21,7 @@
*
* @author Kyle McCarty
*/
-public class EcalWiringManager {
+public class EcalWiringManager implements Iterable<CrystalDataSet> {
// Delimiter class statics.
public static final int SPACE_DELIMITED = 1;
public static final int TAB_DELIMITED = 2;
@@ -109,4 +113,35 @@
* if the crystal index is invalid.
*/
public CrystalDataSet getCrystalData(Point crystalIndex) { return crystalMap.get(crystalIndex); }
+
+ /**
+ * Generates a list of all the crystals that match the conditions
+ * set in the argument <code>Comparator</code> object.
+ * @param conditions - An object defining the conditions that denote
+ * a "matched" crystal.
+ * @return Returns <code>Point</code> objects that contain the
+ * LCSim coordinates of all the crystals that produce a result of
+ * <code>true</code> with the method <code>comparator.equals(crystal)
+ * </code>.
+ */
+ public List<Point> getFilteredCrystalList(Comparator<CrystalDataSet> conditions) {
+ // Create a list of crystal indices that match the conditions.
+ List<Point> crystalList = new ArrayList<Point>();
+
+ // Iterate over the crystal data set entries.
+ for(CrystalDataSet cds : this) {
+ // Check if the crystal data set meets the given conditions.
+ if(conditions.equals(cds)) {
+ crystalList.add(cds.getCrystalIndex());
+ }
+ }
+
+ // Return the resultant list.
+ return crystalList;
+ }
+
+ @Override
+ public Iterator<CrystalDataSet> iterator() {
+ return new MapValueIterator<CrystalDataSet>(crystalMap);
+ }
}
Added: java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/util/MapValueIterator.java
=============================================================================
--- java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/util/MapValueIterator.java (added)
+++ java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/util/MapValueIterator.java Mon Nov 3 11:46:24 2014
@@ -0,0 +1,39 @@
+package org.hps.monitoring.ecal.eventdisplay.util;
+
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+
+/**
+ * Class <code>MapValueIterator</code> creates an iterator for the
+ * values stored in a map.
+ *
+ * @author Kyle McCarty
+ * @param E The object type of the map's values.
+ */
+public class MapValueIterator<E> implements Iterator<E> {
+ private Iterator<? extends Entry<?, E>> baseIterator;
+
+ /**
+ * Generates a new <code>MapValueIterator</code> from a given <code>
+ * Map</code> with the appropriate parameterizations.
+ */
+ public MapValueIterator(Map<?, E> sourceMap) { baseIterator = sourceMap.entrySet().iterator(); }
+
+ @Override
+ public boolean hasNext() { return baseIterator.hasNext(); }
+
+ @Override
+ public E next() {
+ // Get the next entry in the base iterator.
+ Entry<?, E> next = baseIterator.next();
+
+ // Return the value of the entry.
+ return next.getValue();
+ }
+
+ @Override
+ public void remove() throws UnsupportedOperationException {
+ throw new UnsupportedOperationException("Operation \"remove\" is not supported for MapValueIterator.");
+ }
+}
|