LISTSERV mailing list manager LISTSERV 16.5

Help for HPS-SVN Archives


HPS-SVN Archives

HPS-SVN Archives


HPS-SVN@LISTSERV.SLAC.STANFORD.EDU


View:

Message:

[

First

|

Previous

|

Next

|

Last

]

By Topic:

[

First

|

Previous

|

Next

|

Last

]

By Author:

[

First

|

Previous

|

Next

|

Last

]

Font:

Proportional Font

LISTSERV Archives

LISTSERV Archives

HPS-SVN Home

HPS-SVN Home

HPS-SVN  November 2014

HPS-SVN November 2014

Subject:

r1425 - in /java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay: ui/CrystalFilterPanel.java ui/DataFileViewer.java ui/PDataEventViewer.java util/CrystalDataSet.java util/EcalWiringManager.java util/MapValueIterator.java

From:

[log in to unmask]

Reply-To:

Notification of commits to the hps svn repository <[log in to unmask]>

Date:

Mon, 3 Nov 2014 19:46:27 -0000

Content-Type:

text/plain

Parts/Attachments:

Parts/Attachments

text/plain (1441 lines)

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.");
+    }
+}

Top of Message | Previous Page | Permalink

Advanced Options


Options

Log In

Log In

Get Password

Get Password


Search Archives

Search Archives


Subscribe or Unsubscribe

Subscribe or Unsubscribe


Archives

November 2017
August 2017
July 2017
January 2017
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
December 2013
November 2013

ATOM RSS1 RSS2



LISTSERV.SLAC.STANFORD.EDU

Secured by F-Secure Anti-Virus CataList Email List Search Powered by the LISTSERV Email List Manager

Privacy Notice, Security Notice and Terms of Use