Print

Print


Author: mccaky
Date: Thu Dec 11 16:21:05 2014
New Revision: 1702

Log:
Updated EcalEventDisplay driver. Code was cleaned, extraneous variables removed, and code changed such that a new event display is not created for every detectorChanged event.

Modified:
    java/trunk/monitoring-drivers/src/main/java/org/hps/monitoring/ecal/plots/EcalEventDisplay.java

Modified: java/trunk/monitoring-drivers/src/main/java/org/hps/monitoring/ecal/plots/EcalEventDisplay.java
 =============================================================================
--- java/trunk/monitoring-drivers/src/main/java/org/hps/monitoring/ecal/plots/EcalEventDisplay.java	(original)
+++ java/trunk/monitoring-drivers/src/main/java/org/hps/monitoring/ecal/plots/EcalEventDisplay.java	Thu Dec 11 16:21:05 2014
@@ -2,8 +2,6 @@
 
 import hep.aida.IHistogram1D;
 import hep.aida.IHistogram2D;
-import hep.aida.ICloud1D;
-import hep.aida.ICloud2D;
 import hep.aida.IPlotter;
 import hep.aida.IPlotterFactory;
 import hep.aida.IPlotterStyle;
@@ -14,17 +12,12 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.lang.System;
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
 import java.io.File;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
 import java.io.IOException;
 
-import org.hps.monitoring.ecal.eventdisplay.event.Cluster;
-import org.hps.monitoring.ecal.eventdisplay.event.EcalHit;
 import org.hps.monitoring.ecal.eventdisplay.ui.PDataEventViewer;
 import org.hps.monitoring.ecal.eventdisplay.ui.PEventViewer;
+import org.hps.monitoring.ecal.eventdisplay.ui.Viewer;
 import org.hps.monitoring.ecal.eventdisplay.util.CrystalEvent;
 import org.hps.monitoring.ecal.eventdisplay.util.CrystalListener;
 import org.hps.recon.ecal.ECalUtils;
@@ -37,423 +30,453 @@
 import org.lcsim.util.aida.AIDA;
 
 /**
- *  The driver <code>EcalEventDisplay</code> implements the histogram shown to the user 
- * in the fifth tab of the Monitoring Application, when using the Ecal monitoring lcsim file.
- * IT ALSO OPENS KYLE's EVENT DISPLAY <code>PEventViewer</code>.
+ * Driver <code>EcalEventDisplay</code> generates the histograms shown
+ * to the user in the fifth tab of the monitoring application. An
+ * instance of the single event display is employed to allow for the
+ * selection of specific crystal channels.<br/>
+ * <br/>
  * The implementation is as follows:
- * - The event display is opened in a separate window
- * - It is updated regularly, according to the event refresh rate
- * - If the user clicks on a crystal, the corresponding energy and time distributions (both Histogram1D) are shown in the last panel of the MonitoringApplication,
- * as well as a 2D histogram (hit time vs hit energy). Finally, if available, the raw waveshape (in mV) is displayed.
+ * <ul><li>The event display is opened in a separate window</li>
+ * <li>It is updated regularly, according to the event refresh rate</li>
+ * <li>If the user clicks on a crystal, the corresponding energy and time
+ * distributions (both of type <code>IHistogram1D</code>) are shown in
+ * the last panel of the monitoring application, as well as a 2D histogram
+ * (hit time vs. hit energy). Finally, if available, the raw waveshape (in
+ * mV) is displayed.</li>
  * 
  * @author Andrea Celentano
- *  *
  */
-
 public class EcalEventDisplay extends Driver implements CrystalListener, ActionListener {
-
-  
-    String inputCollection = "EcalCalHits";
-    String inputCollectionRaw = "EcalReadoutHits";
-    String clusterCollection = "EcalClusters";
-    private IPlotter plotter;
-    private AIDA aida=AIDA.defaultInstance();
-    private Detector detector;
-    private IPlotterFactory plotterFactory;
-    int eventRefreshRate = 1;
-    int eventn = 0;
-	int ix,iy,id;
-	int pedSamples=10;
-	
-	double amp,ped,sigma;
-	double hitE;
-    int[] windowRaw=new int[47*11];//in case we have the raw waveform, this is the window lenght (in samples)
-	boolean[] isFirstRaw=new boolean[47*11];
-	
-	
-	
-	private PEventViewer viewer; //this is the Kyle event viewer.    
-
-    
-    ArrayList<IHistogram1D> channelEnergyPlot;
-    ArrayList<IHistogram1D> channelTimePlot;
-    ArrayList<IHistogram1D> channelRawWaveform;
-   // ArrayList<ICloud1D> channelRawWaveform;
-    ArrayList<IHistogram2D> channelTimeVsEnergyPlot;
-   
-    IPlotterStyle pstyle;
-    
-    
-    double maxEch = 3500 * ECalUtils.MeV;
-    double minEch = 10* ECalUtils.MeV;
-    
-    int itmpx,itmpy;
-    
-    long thisTime,prevTime;
-    
-    public EcalEventDisplay() {
-    	
-    }
-
-   
-    
-    public void setMaxEch(double maxEch) {
-        this.maxEch = maxEch;
-    }
-    
-    public void setMinEch(double minEch) {
-        this.minEch = minEch;
-    }
-    
-    public void setPedSamples(int pedSamples) {
-        this.pedSamples = pedSamples;
-    }
-    
-    public void setInputCollection(String inputCollection) {
-        this.inputCollection = inputCollection;
-    }
-    
-    public void setInputCollectionRaw(String inputCollectionRaw) {
-        this.inputCollectionRaw = inputCollectionRaw;
-    }
-    
-    public void setInputClusterCollection(String inputClusterCollection) {
-        this.clusterCollection = inputClusterCollection;
-    }
-    
-    public void setEventRefreshRate(int eventRefreshRate) {
-        this.eventRefreshRate = eventRefreshRate;
-    }
-    
-    @Override
-    public void detectorChanged(Detector detector) {
-    	System.out.println("Ecal event display detector changed");
-        this.detector = detector;
-    	
-    	aida.tree().cd("/");
-    	
-      
-    	
-       channelEnergyPlot=new ArrayList<IHistogram1D>();
-       channelTimePlot=new ArrayList<IHistogram1D>();
-       channelRawWaveform=new ArrayList<IHistogram1D>();
-       //channelRawWaveform=new ArrayList<ICloud1D>();
-       channelTimeVsEnergyPlot=new ArrayList<IHistogram2D>();
-       //create the histograms for single channel energy and time distribution.
-       for(int ii = 0; ii < (47*11); ii = ii +1){
-             int row=ECalUtils.getRowFromHistoID(ii);
-             int column=ECalUtils.getColumnFromHistoID(ii);      
-             channelEnergyPlot.add(aida.histogram1D(detector.getDetectorName() + " : " + inputCollection + " : Hit Energy : " + (column) + " "+ (row)+ ": "+ii, 100, -.2, maxEch));  
-             channelTimePlot.add(aida.histogram1D(detector.getDetectorName() + " : " + inputCollection + " : Hit Time : " + (column) + " "+ (row)+ ": "+ii, 100, 0, 400));     
-             channelTimeVsEnergyPlot.add(aida.histogram2D(detector.getDetectorName() + " : " + inputCollection + " : Hit Time Vs Energy : " + (column) + " "+ (row)+ ": "+ii, 100, 0, 400,100, -.2, maxEch));              
-             channelRawWaveform.add(aida.histogram1D(detector.getDetectorName() + " : " + inputCollection + " : Hit Energy : " + (column) + " "+ (row)+ ": "+ii));
-             //the above instruction is a terrible hack, just to fill the arrayList with all the elements. They'll be initialized properly during the event readout,
-             //since we want to account for possibly different raw waveform dimensions!
-             //channelRawWaveform.add(aida.cloud1D(detector.getDetectorName() + " : " + inputCollection + " : Raw Waveform : " + (column) + " "+ (row)+ ": "+ii,1000000000));
-             
-             isFirstRaw[ii]=true;
-             windowRaw[ii]=1;
-       }
-       id=0;
-       iy=ECalUtils.getRowFromHistoID(id);
-   	   ix=ECalUtils.getColumnFromHistoID(id);  
-   	   
-   	   
-    	plotterFactory = aida.analysisFactory().createPlotterFactory("Single channel");       
-        plotter = plotterFactory.create("Single channel");
-   	    pstyle = this.createDefaultStyle(); 		
-        plotter.setTitle("");
-   
-     
-        plotter.createRegions(2,2);
-
-
-        pstyle.xAxisStyle().setLabel("Hit energy (GeV)");
-        pstyle.yAxisStyle().setLabel("");
-        plotter.region(0).plot(channelEnergyPlot.get(id),pstyle);
-   
-        pstyle.xAxisStyle().setLabel("Hit Time (ns)");
-        pstyle.yAxisStyle().setLabel("");    
-        plotter.region(1).plot(channelTimePlot.get(id),pstyle);           	    
-        
-        pstyle.xAxisStyle().setLabel("Hit Time (ns)");
-        pstyle.yAxisStyle().setLabel("Hit Energy (GeV)");    
-    	plotter.region(2).plot(channelTimeVsEnergyPlot.get(id),pstyle);
-
-    	pstyle.xAxisStyle().setLabel("Hit Energy (GeV)");    
-        pstyle.yAxisStyle().setLabel("");
-        pstyle.dataStyle().fillStyle().setColor("orange");
-        pstyle.dataStyle().markerStyle().setColor("orange");
-        pstyle.dataStyle().errorBarStyle().setVisible(false);
-	    plotter.region(3).plot(channelRawWaveform.get(id),pstyle);
-	
-        
-        
-        System.out.println("Create the event viewer");
-        // Check if the configuration mapping file exists.
-        File config = new File("ecal-mapping-config.csv");
-        
-        // If the file exists, load the viewer that will display it.
-        if(config.exists() && config.canRead()) {
-        	// Account for IO read errors. Only load this version if
-        	// the data file can be read successfully.
-        	try {
-				viewer = new PDataEventViewer(config.getAbsolutePath());
+	// Class variables.
+	private static final int NUM_CHANNELS = 11 * 47;
+	
+	// Plotter objects and variables.
+	private IPlotter plotter;
+	private IPlotterFactory plotterFactory;
+	private AIDA aida = AIDA.defaultInstance();	
+	
+	// LCIO Collection names.
+	private String inputCollection = "EcalCalHits";
+	private String clusterCollection = "EcalClusters";
+	private String inputCollectionRaw = "EcalReadoutHits";
+	
+	// Channel plot lists.
+	private ArrayList<IHistogram1D> channelEnergyPlot;
+	private ArrayList<IHistogram1D> channelTimePlot;
+	private ArrayList<IHistogram1D> channelRawWaveform;
+	private ArrayList<IHistogram2D> channelTimeVsEnergyPlot;
+	
+	// Internal variables.
+	private Detector detector;									 // The active detector.
+	private PEventViewer viewer;								 // Single event display.
+	private int pedSamples = 10;								 // 
+	private IPlotterStyle pstyle;								 // The plotter style for all plots.
+	private long lastEventTime = 0;							 // Tracks the time at which the last event occurred.
+	private int eventRefreshRate = 1;							 // The number of seconds before an update occurs.
+	private double minEch = 10 * ECalUtils.MeV;				 // The energy scale minimum.
+	private double maxEch = 3500 * ECalUtils.MeV;				 // The energy scale maximum.
+	private int[] windowRaw = new int[NUM_CHANNELS];			 // The number of samples in a waveform for each channel.
+	private boolean[] isFirstRaw = new boolean[NUM_CHANNELS]; // Whether a waveform plot was initiated for each channel.
+	
+	// Plot style and title variables.
+	private static final String NO_TITLE = "";
+	private static final String SIGNAL_TIME_TITLE = "Time (ns)";
+	private static final String HIT_TIME_TITLE = "Hit Time (ns)";
+	private static final String SIGNAL_DATA_STYLE_COLOR = "orange";
+	private static final String HIT_ENERGY_TITLE = "Hit Energy (GeV)";
+	private static final String SIGNAL_AMPLITUDE_TITLE = "Signal Amplitude (mV)";
+	
+	/**
+	 * Sets the upper bound of the energy scales used by the driver.
+	 * Energy units are in GeV.
+	 * @param maxEch - The energy scale upper bound.
+	 */
+	public void setMaxEch(double maxEch) {
+		this.maxEch = maxEch;
+	}
+	
+	/**
+	 * Sets the lower bound of the energy scales used by the driver.
+	 * Energy units are in GeV.
+	 * @param minEch - The lower energy scale bound.
+	 */
+	public void setMinEch(double minEch) {
+		this.minEch = minEch;
+	}
+	
+	public void setPedSamples(int pedSamples) {
+		this.pedSamples = pedSamples;
+	}
+	/**
+	 * Sets the LCIO collection name for the processed calorimeter hits.
+	 * @param inputCollection - The LCIO collection name.
+	 */
+	public void setInputCollection(String inputCollection) {
+		this.inputCollection = inputCollection;
+	}
+	
+	/**
+	 * Sets the LCIO collection name for the raw waveform hits.
+	 * @param inputCollectionRaw - The LCIO collection name.
+	 */
+	public void setInputCollectionRaw(String inputCollectionRaw) {
+		this.inputCollectionRaw = inputCollectionRaw;
+	}
+	
+	/**
+	 * Sets the LCIO collection name for calorimeter clusters.
+	 * @param inputClusterCollection - The LCIO collection name.
+	 */
+	public void setInputClusterCollection(String inputClusterCollection) {
+		this.clusterCollection = inputClusterCollection;
+	}
+	
+	/**
+	 * Sets the rate at which the GUI updates its elements,
+	 * @param eventRefreshRate - The rate at which the GUI should be
+	 * updated, in seconds.
+	 */
+	public void setEventRefreshRate(int eventRefreshRate) {
+		this.eventRefreshRate = eventRefreshRate;
+	}
+	
+	/**
+	 * Initializes the single channel monitoring plots for all crystal
+	 * channels and defines the plotter region that contains them.
+	 */
+	@Override
+	public void detectorChanged(Detector detector) {
+		// Store the current detector.
+		this.detector = detector;
+		
+		// Reset the AIDA tree directory.
+		aida.tree().cd("/");
+		
+		// Store histograms for the crystals.
+		channelEnergyPlot = new ArrayList<IHistogram1D>();
+		channelTimePlot = new ArrayList<IHistogram1D>();
+		channelRawWaveform = new ArrayList<IHistogram1D>();
+		channelTimeVsEnergyPlot = new ArrayList<IHistogram2D>();
+		
+		// Create the histograms for single channel energy and time
+		// distribution.
+		for(int ii = 0; ii < (47 * 11); ii++) {
+			// The above instruction is a terrible hack, just to fill
+			// the arrayList with all the elements. They'll be initialized
+			// properly during the event readout, Since we want to account
+			// for possibly different raw waveform dimensions!
+			
+			//Get the x and y indices for the current channel.
+			int row = ECalUtils.getRowFromHistoID(ii);
+			int column = ECalUtils.getColumnFromHistoID(ii);
+			
+			// Initialize the histograms for the current crystal channel.
+			channelEnergyPlot.add(aida.histogram1D(detector.getDetectorName() + " : "
+						+ inputCollection + " : Hit Energy : " + column + " " + row
+						+ ": " + ii, 100, -0.2, maxEch));  
+			channelTimePlot.add(aida.histogram1D(detector.getDetectorName() + " : "
+						+ inputCollection + " : Hit Time : " + column + " " + row + ": "
+						+ ii, 100, 0, 400));     
+			channelTimeVsEnergyPlot.add(aida.histogram2D(detector.getDetectorName()
+					+ " : " + inputCollection + " : Hit Time Vs Energy : " + column
+					+ " " + row + ": " + ii, 100, 0, 400, 100, -0.2, maxEch));              
+			channelRawWaveform.add(aida.histogram1D(detector.getDetectorName() + " : "
+					+ inputCollection + " : Hit Energy : " + column + " " + row + ": " + ii));
+			
+			// Note that no raw waveform has yet been read for this
+			// crystal/channel.
+			windowRaw[ii] = 1;
+			isFirstRaw[ii] = true;
+		}
+		
+		// Define the plot region that will display the single channel
+		// plots in the monitoring application.
+		plotterFactory = aida.analysisFactory().createPlotterFactory("Single Channel");
+		plotter = plotterFactory.create("Single Channel");
+		pstyle = this.createDefaultStyle();
+		plotter.setTitle("");
+		plotter.createRegions(2,2);
+		
+		// Define the first plot region.
+		pstyle.xAxisStyle().setLabel(HIT_ENERGY_TITLE);
+		pstyle.yAxisStyle().setLabel(NO_TITLE);
+		plotter.region(0).plot(channelEnergyPlot.get(0), pstyle);
+		
+		// Define the second plot region.
+		pstyle.xAxisStyle().setLabel(HIT_TIME_TITLE);
+		pstyle.yAxisStyle().setLabel(NO_TITLE);
+		plotter.region(1).plot(channelTimePlot.get(0), pstyle);
+		
+		// Define the third plot region; this encompasses the time vs.
+		// energy plots.
+		pstyle.xAxisStyle().setLabel(HIT_TIME_TITLE);
+		pstyle.yAxisStyle().setLabel(HIT_ENERGY_TITLE);
+		plotter.region(2).plot(channelTimeVsEnergyPlot.get(0), pstyle);
+		
+		// Define the fourth plot region; this encompasses the raw
+		// wave form plots.
+		pstyle.xAxisStyle().setLabel(HIT_ENERGY_TITLE);
+		pstyle.yAxisStyle().setLabel(NO_TITLE);
+		pstyle.dataStyle().fillStyle().setColor(SIGNAL_DATA_STYLE_COLOR);
+		pstyle.dataStyle().markerStyle().setColor(SIGNAL_DATA_STYLE_COLOR);
+		pstyle.dataStyle().errorBarStyle().setVisible(false);
+		plotter.region(3).plot(channelRawWaveform.get(0), pstyle);
+		
+		// Display the plot region.
+		plotter.show();
+		
+		// Set the time tracker variables.
+		lastEventTime = 0;
+	}
+	
+	/**
+	 * Initializes the <code>Viewer</code> for the single event display.
+	 * If a configuration file is available, then it is used by the
+	 * <code>Viewer</code> to display hardware configuration mappings.
+	 * Otherwise, this is excluded.
+	 */
+	@Override
+	public void startOfData() {
+		// Check if the configuration mapping file exists.
+		File config = new File("ecal-mapping-config.csv");
+		
+		// If the file exists, load the viewer that will display it.
+		if(config.exists() && config.canRead()) {
+			// Account for IO read errors. Only load this version if
+			// the data file can be read successfully.
+			try { viewer = new PDataEventViewer(config.getAbsolutePath()); }
+			
+			// Otherwise, open the regular version.
+			catch (IOException e) { viewer = new PEventViewer(); }
+		}
+		
+		// If the file is not present, then just load the normal version.
+		else { viewer = new PEventViewer(); }
+		
+		// Set the viewer properties.
+		viewer.setScaleMinimum(minEch);
+		viewer.setScaleMaximum(maxEch);
+		viewer.addCrystalListener(this);
+		
+		// Make the Viewer object visible.
+		viewer.setVisible(true);
+	}
+	
+	/**
+	 * Hides the single event display and disposes it from memory.
+	 */
+	@Override
+	public void endOfData() {
+		viewer.setVisible(false);
+		viewer.dispose();
+	}
+	
+	@Override
+	public void process(EventHeader event){
+		// Check whether enough time has passed to perform an update
+		// on the event display.
+		boolean update = false;
+		long currentTime = System.currentTimeMillis() / 1000;
+		if((currentTime - lastEventTime) > eventRefreshRate){
+			lastEventTime = currentTime;
+			update = true;
+		}
+		
+		// If an update should be made, perform the update.
+		if(update) { viewer.resetDisplay(); }
+		
+		// If the event has calorimeter hit objects...
+		if(event.hasCollection(CalorimeterHit.class, inputCollection)) {
+			// Get the list of calorimeter hits.
+			List<CalorimeterHit> hits = event.get(CalorimeterHit.class, inputCollection);
+			
+			// For each of the calorimeter hits...
+			for (CalorimeterHit hit : hits) {
+				// Get the x and y indices for the current hit.
+				int ix = hit.getIdentifierFieldValue("ix");
+				int iy = hit.getIdentifierFieldValue("iy");
+				
+				if (iy != 0 && ix != 0) {
+					// Get the histogram index for the hit.
+					int id = ECalUtils.getHistoIDFromRowColumn(iy, ix);
+					
+					// If the hit has energy, populate the plots.
+					if(hit.getCorrectedEnergy() > 0) {
+						channelEnergyPlot.get(id).fill(hit.getCorrectedEnergy());
+						channelTimePlot.get(id).fill(hit.getTime());
+						channelTimeVsEnergyPlot.get(id).fill(hit.getTime(), hit.getCorrectedEnergy());
+					}
+					
+					// If an update to the event display should be
+					// performed, give it the hits.
+					if(update) { viewer.addHit(hit); }
+				}
 			}
-        	
-        	// Otherwise, open the regular version.
-        	catch (IOException e) {
-				viewer = new PEventViewer();
+		}
+		
+		// If there are clusters in the event...
+		if (event.hasCollection(HPSEcalCluster.class, clusterCollection)) {
+			// Get the list of clusters.
+			List<HPSEcalCluster> clusters = event.get(HPSEcalCluster.class, clusterCollection);
+			
+			// Iterate over the clusters and add them to the event
+			// display if appropriate.
+			for (HPSEcalCluster cluster : clusters) {
+				if(update) { viewer.addCluster(cluster); }
 			}
-        }
-        
-        // If the file is not present, then just load the normal version.
-        else {
-        	viewer = new PEventViewer();
-        }
-        
-        // Set the viewer properties.
-        viewer.addCrystalListener(this);
-        viewer.setScaleMinimum(minEch);
-        viewer.setScaleMaximum(maxEch);
-        System.out.println("Done");
-        
-      
-        plotter.show();
-       
-        viewer.setVisible(true);
-        
-        prevTime=0; //init the time 
-        thisTime=0; //init the time 
-    }
-
-    @Override
-    public void endOfData() {
-        viewer.setVisible(false);
-        viewer.dispose();
-    }
-
-    @Override
-    public void process(EventHeader event){
-    	
-    	  int ii;
-          int row = 0;
-          int column = 0;
-          double[] result;
-          
-          boolean do_update=false;
-          thisTime=System.currentTimeMillis()/1000;
-          
-          if ((thisTime-prevTime)>eventRefreshRate){
-        	  prevTime=thisTime;
-        	  do_update=true;
-          }   	
-    	  if (do_update){
-          	viewer.resetDisplay();
-    	    viewer.updateDisplay();
-    	  }
-    
-    	Cluster the_cluster;
-    	
-        if (event.hasCollection(CalorimeterHit.class, inputCollection)) {
-        	List<CalorimeterHit> hits = event.get(CalorimeterHit.class, inputCollection);
-            for (CalorimeterHit hit : hits) {
-                row=hit.getIdentifierFieldValue("iy");
-                column=hit.getIdentifierFieldValue("ix");           	
-                if ((row!=0)&&(column!=0)){
-                    ii = ECalUtils.getHistoIDFromRowColumn(row,column);
-                    hitE=hit.getCorrectedEnergy();
-                    if (hitE > 0) { //A.C. > 0 for the 2D plot drawing                 	
-                    	channelEnergyPlot.get(ii).fill(hit.getCorrectedEnergy());
-                        channelTimePlot.get(ii).fill(hit.getTime());
-                        channelTimeVsEnergyPlot.get(ii).fill(hit.getTime(),hit.getCorrectedEnergy());                                    
-                    }
-                    if ((do_update)){
-                    	if ((hitE>minEch)&&(hitE<maxEch)){
-                    		viewer.addHit(new EcalHit(column,row, hitE));  //before was in >0 check
-                    	}
-                    	else if (hitE>maxEch){
-                    		viewer.addHit(new EcalHit(column,row, maxEch));  
-                    	}                	
-                    }
-                 } 
-            }
-        }
-        if (event.hasCollection(HPSEcalCluster.class, clusterCollection)) {
-            List<HPSEcalCluster> clusters = event.get(HPSEcalCluster.class, clusterCollection);
-            for (HPSEcalCluster cluster : clusters) {
-                CalorimeterHit seedHit = cluster.getSeedHit();
-                if (do_update){
-                the_cluster=new Cluster(seedHit.getIdentifierFieldValue("ix"), seedHit.getIdentifierFieldValue("iy"), cluster.getEnergy());
-                for (CalorimeterHit hit : cluster.getCalorimeterHits()) {
-                	hitE=hit.getCorrectedEnergy();
-                	if ((hitE>minEch)&&(hitE<maxEch)){               
-                		column=hit.getIdentifierFieldValue("ix");
-                        row=hit.getIdentifierFieldValue("iy");                	
-                        the_cluster.addComponentHit(hit.getIdentifierFieldValue("ix"),hit.getIdentifierFieldValue("iy"));
-                    }
-                }         
-                viewer.addCluster(the_cluster);
-               }
-            }
-        }
-        
-        //here follows the code for the raw waveform
-        if (event.hasCollection(RawTrackerHit.class, inputCollectionRaw)){       	
-        	List<RawTrackerHit> hits = event.get(RawTrackerHit.class, inputCollectionRaw);
-        	for (RawTrackerHit hit : hits) {
-        		 row=hit.getIdentifierFieldValue("iy");
-                 column=hit.getIdentifierFieldValue("ix");
-                 if ((row!=0)&&(column!=0)){
-                	 if (!ECalUtils.isInHole(row,column)){
-                	 
-                		 ii = ECalUtils.getHistoIDFromRowColumn(row,column);
-                		 if (isFirstRaw[ii]){ //at the very first hit we read for this channel, we need to read the window length and save it
-                			 isFirstRaw[ii]=false;
-                			 windowRaw[ii]=hit.getADCValues().length;                   	 
-                			 channelRawWaveform.set(ii,aida.histogram1D(detector.getDetectorName() + " : " + inputCollectionRaw + " : Raw Waveform : " + (column) + " "+ (row)+ ": "+ii,windowRaw[ii],-0.5*ECalUtils.ecalReadoutPeriod,(-0.5+windowRaw[ii])*ECalUtils.ecalReadoutPeriod));
-                		 }
-                		 if (do_update){
-                			 channelRawWaveform.get(ii).reset();                     
-                			 for (int jj = 0; jj < windowRaw[ii]; jj++) {
-                				 channelRawWaveform.get(ii).fill(jj*ECalUtils.ecalReadoutPeriod, hit.getADCValues()[jj]*ECalUtils.adcResolution*1000);
-                			 }                  
-                			 result=ECalUtils.computeAmplitude(hit.getADCValues(),windowRaw[ii],pedSamples);
-                			 channelRawWaveform.get(ii).setTitle("Ampl: "+String.format("%.2f",result[0])+" mV , ped : "+String.format("%.2f",result[1])+" "+String.format("%.2f",result[2])+" ADC counts");
-                			 plotter.region(3).refresh();
-                		 } 	
-                	 }
-                 }
-            }
-        }
-        
-        
-        if (do_update){
-          viewer.updateDisplay(); 
-        }
-    }
-    
-    /*
-    @Override
-    public void reset(){
-        for(int ii = 0; ii < (47*11); ii = ii +1){         
-            channelEnergyPlot.get(ii).reset();
-            channelTimePlot.get(ii).reset();
-            channelTimeVsEnergyPlot.get(ii).reset();
-        }
-    }
-    */
-    
-    @Override
-    public void actionPerformed(ActionEvent ae) {
-     
-    }
-                  
-    @Override
-    public void crystalActivated(CrystalEvent e){
-		
-	}
-	
-	/**
-	 * <b>crystalDeactivated</b><br/><br/>
-	 * <code>public void <b>crystalDeactivated</b>(CrystalEvent e)</code><br/><br/>
-	 * Invoked when a crystal ceases to be highlighted.
-	 * @param e - An object describing the event.
-	 */
-    @Override
-	public void crystalDeactivated(CrystalEvent e){
-		
-	}
-	
-	/**
-	 * <b>crystalClicked</b><br/><br/>
-	 * <code>public void <b>crystalClicked</b>(CrystalEvent e)</code><br/><br/>
-	 * Invoked when a crystal is clicked
-	 * @param e - An object describing the event.
-	 */
-    @Override
-	public void crystalClicked(CrystalEvent e){
-    
-    	
-    	Point displayPoint,ecalPoint;
-    	displayPoint=e.getCrystalID();
-    	ecalPoint=viewer.toEcalPoint(displayPoint);
-    	itmpx=(int) ecalPoint.getX(); //column
-    	itmpy=(int) ecalPoint.getY(); //row
-    	
-    	if ((itmpx!=0)&&(itmpy!=0))
-    		if (!ECalUtils.isInHole(itmpy,itmpx)){
-    			ix=itmpx;
-    			iy=itmpy;
-    			id=ECalUtils.getHistoIDFromRowColumn(iy,ix);
-    			System.out.println("Crystal event: "+ix+" "+iy+" "+id);
-        
-    	    
-    	    
-    	    
-    	    
-    			plotter.region(0).clear();
-    			pstyle.xAxisStyle().setLabel("Hit energy (GeV)");
-    			pstyle.yAxisStyle().setLabel("");
-    			plotter.region(0).plot(channelEnergyPlot.get(id),pstyle);
-       
-    			plotter.region(1).clear();
-    			pstyle.xAxisStyle().setLabel("Hit Time (ns)");
-    			pstyle.yAxisStyle().setLabel("");    
-    			plotter.region(1).plot(channelTimePlot.get(id),pstyle);           	    
-     
-    			plotter.region(2).clear();
-    			pstyle.xAxisStyle().setLabel("Hit Time (ns)");
-    			pstyle.yAxisStyle().setLabel("Hit Energy (GeV)");    
-    			plotter.region(2).plot(channelTimeVsEnergyPlot.get(id),pstyle);
-
-    			plotter.region(3).clear();
-        	
-        	 
-    			if (!isFirstRaw[id]){
-    				pstyle.yAxisStyle().setLabel("Signal amplitude (mV)");
-    				pstyle.xAxisStyle().setLabel("Time (ns)");
-    				pstyle.dataStyle().fillStyle().setColor("orange");
-    				pstyle.dataStyle().markerStyle().setColor("orange");
-    				pstyle.dataStyle().errorBarStyle().setVisible(false);
-    			}
-    			else{
-    				pstyle.xAxisStyle().setLabel("Hit Energy (GeV)");    
-    				pstyle.yAxisStyle().setLabel("");  	    
-    			}
-    			plotter.region(3).plot(channelRawWaveform.get(id),pstyle);       
-    	}
-    }    
-    
-    
-    /*
-     * This method set the default style.
-     */
-    public IPlotterStyle createDefaultStyle() {
-    	IPlotterStyle pstyle = plotterFactory.createPlotterStyle();
-    	// Axis appearence.
-    	pstyle.xAxisStyle().labelStyle().setBold(true);
-    	pstyle.yAxisStyle().labelStyle().setBold(true);
-    	pstyle.xAxisStyle().tickLabelStyle().setBold(true);
-    	pstyle.yAxisStyle().tickLabelStyle().setBold(true);
-    	pstyle.xAxisStyle().lineStyle().setColor("black");
-    	pstyle.yAxisStyle().lineStyle().setColor("black");
-    	pstyle.xAxisStyle().lineStyle().setThickness(2);
-    	pstyle.yAxisStyle().lineStyle().setThickness(2);
-    	
-    	pstyle.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
-    	pstyle.dataStyle().fillStyle().setParameter("showZeroHeightBins",Boolean.FALSE.toString());
-    	pstyle.dataStyle().errorBarStyle().setVisible(false);
-        pstyle.setParameter("hist2DStyle", "colorMap");
-    	// Force auto range to zero.
-    	pstyle.yAxisStyle().setParameter("allowZeroSuppression", "false");
-    	pstyle.xAxisStyle().setParameter("allowZeroSuppression", "false");
-    	// Title style.
-    	pstyle.titleStyle().textStyle().setFontSize(20);
-    	// Draw caps on error bars.
-    	pstyle.dataStyle().errorBarStyle().setParameter("errorBarDecoration", (new Float(1.0f)).toString());
-    	// Turn off grid lines until explicitly enabled.
-    	pstyle.gridStyle().setVisible(false);
-    	return pstyle;
-    	}   
+		}
+		
+		// Plot the raw waveform only if raw tracker hit exist in the
+		// event.
+		if (event.hasCollection(RawTrackerHit.class, inputCollectionRaw)){
+			// Get the list of raw tracker hits.
+			List<RawTrackerHit> hits = event.get(RawTrackerHit.class, inputCollectionRaw);
+			
+			// Process each raw tracker hit.
+			for (RawTrackerHit hit : hits) {
+				// Get the x and y indices for the hit.
+				int ix = hit.getIdentifierFieldValue("ix");
+				int iy = hit.getIdentifierFieldValue("iy");
+				
+				if(iy != 0 && ix != 0) {
+					if(!ECalUtils.isInHole(iy, ix)) {
+						// Get the crystal ID for the current hit.
+						int id = ECalUtils.getHistoIDFromRowColumn(iy, ix);
+						
+						// The window is length is not known by default.
+						// If this is the first hit, read the window
+						// length and initialize the plot.
+						if(isFirstRaw[id]) {
+							// Note that this plot is initialized.
+							isFirstRaw[id] = false;
+							
+							// Set the waveform array.
+							windowRaw[id] = hit.getADCValues().length;
+							
+							// Initialize the waveform plot.
+							channelRawWaveform.set(id, aida.histogram1D(detector.getDetectorName()
+									+ " : " + inputCollectionRaw + " : Raw Waveform : " + ix + " "
+									+ iy + ": " + id, windowRaw[id], -0.5 * ECalUtils.ecalReadoutPeriod,
+									(-0.5 + windowRaw[id]) * ECalUtils.ecalReadoutPeriod));
+						}
+						
+						// If the plot should be updated, do so.
+						if(update) {
+							channelRawWaveform.get(id).reset();
+							for (int jj = 0; jj < windowRaw[id]; jj++) {
+								channelRawWaveform.get(id).fill(jj * ECalUtils.ecalReadoutPeriod,
+										hit.getADCValues()[jj] * ECalUtils.adcResolution * 1000);
+							}
+							double[] result = ECalUtils.computeAmplitude(hit.getADCValues(), windowRaw[id], pedSamples);
+							channelRawWaveform.get(id).setTitle("Ampl: " + String.format("%.2f", result[0])
+									+ " mV , ped : " + String.format("%.2f", result[1]) + " "
+									+ String.format("%.2f", result[2]) + " ADC counts");
+							plotter.region(3).refresh();
+						}
+					}
+				}
+			}
+		}
+		
+		// Update the single event display.
+		if(update) { viewer.updateDisplay(); }
+	}
+	
+	@Override
+	public void actionPerformed(ActionEvent ae) { }
+	
+	@Override
+	public void crystalActivated(CrystalEvent e) { }
+	
+	@Override
+	public void crystalDeactivated(CrystalEvent e) { }
+	
+	/**
+	 * Updates the monitoring plots for the crystal that was clicked.
+	 */
+	@Override
+	public void crystalClicked(CrystalEvent e) {
+		// Get the crystal that was clicked in the LCSim coordinate system.
+		Point ecalPoint = Viewer.toEcalPoint(e.getCrystalID());
+		
+		// Make sure that the clicked crystal is valid. Necessary??
+		if((ecalPoint.x != 0) && (ecalPoint.y != 0))
+			if (!ECalUtils.isInHole(ecalPoint.y, ecalPoint.x)) {
+				// Get the crystal ID.
+				int id = ECalUtils.getHistoIDFromRowColumn(ecalPoint.y, ecalPoint.x);
+				
+				// Clear and replot region 0 for the new crystal.
+				plotter.region(0).clear();
+				pstyle.xAxisStyle().setLabel(HIT_ENERGY_TITLE);
+				pstyle.yAxisStyle().setLabel(NO_TITLE);
+				plotter.region(0).plot(channelEnergyPlot.get(id), pstyle);
+				
+				// Clear and replot region 1 for the new crystal.
+				plotter.region(1).clear();
+				pstyle.xAxisStyle().setLabel(HIT_TIME_TITLE);
+				pstyle.yAxisStyle().setLabel(NO_TITLE);
+				plotter.region(1).plot(channelTimePlot.get(id), pstyle);
+				
+				// Clear and replot region 2 for the new crystal.
+				plotter.region(2).clear();
+				pstyle.xAxisStyle().setLabel(HIT_TIME_TITLE);
+				pstyle.yAxisStyle().setLabel(HIT_ENERGY_TITLE);
+				plotter.region(2).plot(channelTimeVsEnergyPlot.get(id), pstyle);
+				plotter.region(3).clear();
+				
+				// Process and plot the region 3 plot.
+				if(!isFirstRaw[id]) {
+					pstyle.yAxisStyle().setLabel(SIGNAL_AMPLITUDE_TITLE);
+					pstyle.xAxisStyle().setLabel(SIGNAL_TIME_TITLE);
+					pstyle.dataStyle().fillStyle().setColor(SIGNAL_DATA_STYLE_COLOR);
+					pstyle.dataStyle().markerStyle().setColor(SIGNAL_DATA_STYLE_COLOR);
+					pstyle.dataStyle().errorBarStyle().setVisible(false);
+				}
+				else {
+					pstyle.xAxisStyle().setLabel(HIT_ENERGY_TITLE);
+					pstyle.yAxisStyle().setLabel("");
+				}
+				plotter.region(3).plot(channelRawWaveform.get(id), pstyle);
+		}
+	}
+	
+	/**
+	 * Initializes the default style for plots.
+	 * @return Returns an <code>IPlotterStyle</code> object that
+	 * represents the default style for plots.
+	 */
+	public IPlotterStyle createDefaultStyle() {
+		IPlotterStyle pstyle = plotterFactory.createPlotterStyle();
+		// Set the appearance of the axes.
+		pstyle.xAxisStyle().labelStyle().setBold(true);
+		pstyle.yAxisStyle().labelStyle().setBold(true);
+		pstyle.xAxisStyle().tickLabelStyle().setBold(true);
+		pstyle.yAxisStyle().tickLabelStyle().setBold(true);
+		pstyle.xAxisStyle().lineStyle().setColor("black");
+		pstyle.yAxisStyle().lineStyle().setColor("black");
+		pstyle.xAxisStyle().lineStyle().setThickness(2);
+		pstyle.yAxisStyle().lineStyle().setThickness(2);
+		
+		// Set color settings.
+		pstyle.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+		pstyle.dataStyle().fillStyle().setParameter("showZeroHeightBins", Boolean.FALSE.toString());
+		pstyle.dataStyle().errorBarStyle().setVisible(false);
+		pstyle.setParameter("hist2DStyle", "colorMap");
+		
+		// Force auto range to zero.
+		pstyle.yAxisStyle().setParameter("allowZeroSuppression", "false");
+		pstyle.xAxisStyle().setParameter("allowZeroSuppression", "false");
+		
+		// Set the title style.
+		pstyle.titleStyle().textStyle().setFontSize(20);
+		
+		// Draw caps on error bars.
+		pstyle.dataStyle().errorBarStyle().setParameter("errorBarDecoration", (new Float(1.0f)).toString());
+		
+		// Turn off grid lines until explicitly enabled.
+		pstyle.gridStyle().setVisible(false);
+		
+		// Return the style.
+		return pstyle;
+	}
 }