Print

Print


Author: [log in to unmask]
Date: Tue Oct 27 11:33:16 2015
New Revision: 3892

Log:
Other changes to Led analysis

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/EcalEventDisplayWithRawWaveform.java
    java/trunk/monitoring-drivers/src/main/java/org/hps/monitoring/ecal/plots/EcalLedSequenceMonitor.java
    java/trunk/monitoring-drivers/src/main/java/org/hps/monitoring/ecal/plots/EcalMonitoringUtilities.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	Tue Oct 27 11:33:16 2015
@@ -13,6 +13,7 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.lang.IllegalArgumentException;
 
 import javax.swing.SwingUtilities;
 
@@ -67,7 +68,7 @@
     // LCIO Collection names.
     private String inputCollection = "EcalCalHits";
     private String inputCollectionRaw = "EcalReadoutHits";
-    private final boolean[] isFirstRaw = new boolean[NUM_CHANNELS]; // Whether a waveform plot was initiated for each
+  
     // channel.
     private long lastEventTime = 0; // Tracks the time at which the last event occurred.
     private double maxEch = 3500 * EcalUtils.MeV; // The energy scale maximum.
@@ -81,8 +82,7 @@
     private boolean resetOnUpdate = true; // Clears the event display on each update.
     // Internal variables.
     private final PEventViewer viewer; // Single event display.
-    private final int[] windowRaw = new int[NUM_CHANNELS]; // The number of samples in a waveform for each channel.
-
+   
     public EcalEventDisplay() {
         // Check if the configuration mapping file exists.
         final File config = new File("ecal-mapping-config.csv");
@@ -192,16 +192,6 @@
                 this.pstyle.yAxisStyle().setLabel(NO_TITLE);
                 this.plotter.region(3).plot(this.clusterEnergyPlot.get(id), this.pstyle);
 
-                /**
-                 * // 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);
-                 **/
             }
         }
     }
@@ -252,10 +242,8 @@
             this.clusterEnergyPlot.add(this.aida.histogram1D(this.detectorName + " : " + this.inputCollection
                     + " : Cluster Energy : " + column + " " + row + ": " + ii, 100, -0.2, this.maxEch));
 
-            // Note that no raw waveform has yet been read for this
-            // crystal/channel.
-            this.windowRaw[ii] = 1;
-            this.isFirstRaw[ii] = true;
+   
+          
         }
 
         // Define the plot region that will display the single channel
@@ -321,29 +309,43 @@
                 System.out.println("done disposing ECAL event display");
             }
         });
-        // Comment this out for now. It is causing problems. --JM
-        
-        int row,column; 
-        String hName; 
+
+        int row,column; String hName; 
         System.out.println("EcalEventDisplay endOfData clear histograms"); 
         for(int ii = 0; ii < NUM_CHANNELS; ii++) { 
-              row=EcalMonitoringUtilities.getRowFromHistoID(ii);
-        	  column = EcalMonitoringUtilities.getColumnFromHistoID(ii);
-        	  hName=detectorName + " : " + inputCollection + " : Hit Energy : " + column + " " + row + ": " + ii;
-        	  aida.tree().rm(hName);
-        	  hName=detectorName + " : " + inputCollection + " : Hit Time : " + column + " " + row +": " + ii;
-        	  aida.tree().rm(hName);
-        	  hName=detectorName+ " : " + inputCollection + " : Hit Time Vs Energy : " + column + " " + row + ": " + ii; 
-        	  aida.tree().rm(hName); 
-        	  hName=detectorName + " : " + inputCollection +" : Cluster Energy : " + column + " " + row + ": " + ii;
-        	  aida.tree().rm(hName);
-        	  
-        	  
-        	  if (isFirstRaw[ii]==false)          { 
-        		  hName=detectorName+ " : "          + inputCollectionRaw + " : Raw Waveform : " + column + " " + row + ": " + ii; aida.tree().rm(hName); 
-        	  } 
-          }
-          System.out.println("EcalEventDisplay endOfData clear histograms done");
+            row = EcalMonitoringUtilities.getRowFromHistoID(ii);
+            column = EcalMonitoringUtilities.getColumnFromHistoID(ii);
+            hName=detectorName + " : " + inputCollection + " : Hit Energy : " + column + " " + row + ": " + ii;
+            try{
+                aida.tree().rm(hName);
+            }
+            catch(IllegalArgumentException e){
+                System.out.println("Got exception "+e);
+            }
+
+
+
+            hName=detectorName + " : " + inputCollection + " : Hit Time : " + column + " " + row + ": " + ii;
+            try{
+                aida.tree().rm(hName);
+            }
+            catch(IllegalArgumentException e){
+                System.out.println("Got exception "+e);
+            }
+
+
+
+            hName=detectorName+ " : " + inputCollection + " : Hit Time Vs Energy : " + column + " " + row + ": " + ii; 
+            try{
+                aida.tree().rm(hName);
+            }
+            catch(IllegalArgumentException e){
+                System.out.println("Got exception "+e);
+            }
+
+
+        }
+        System.out.println("EcalEventDisplay endOfData clear histograms done");
     }
 
     @Override
@@ -420,35 +422,7 @@
             }
         }
 
-        /**
-         * // 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) {
             this.viewer.updateDisplay();

Modified: java/trunk/monitoring-drivers/src/main/java/org/hps/monitoring/ecal/plots/EcalEventDisplayWithRawWaveform.java
 =============================================================================
--- java/trunk/monitoring-drivers/src/main/java/org/hps/monitoring/ecal/plots/EcalEventDisplayWithRawWaveform.java	(original)
+++ java/trunk/monitoring-drivers/src/main/java/org/hps/monitoring/ecal/plots/EcalEventDisplayWithRawWaveform.java	Tue Oct 27 11:33:16 2015
@@ -13,6 +13,7 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.lang.IllegalArgumentException;
 
 import org.hps.monitoring.ecal.eventdisplay.ui.PDataEventViewer;
 import org.hps.monitoring.ecal.eventdisplay.ui.PEventViewer;
@@ -47,251 +48,251 @@
  * @author Andrea Celentano
  */
 public class EcalEventDisplayWithRawWaveform extends Driver implements CrystalListener, ActionListener {
-	// 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> clusterEnergyPlot;
-	private ArrayList<IHistogram1D> channelTimePlot;
-	private ArrayList<IHistogram1D> channelRawWaveform;
-	private ArrayList<IHistogram2D> channelTimeVsEnergyPlot;
-	
-	// Internal variables.
-	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 boolean resetOnUpdate = true;						 // Clears the event display on each update.
-	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 RAW_WAVEFORM_TITLE = "Raw Waveform";
-	private static final String HIT_ENERGY_TITLE = "Hit Energy (GeV)";
-	private static final String CLUSTER_ENERGY_TITLE = "Cluster Energy (GeV)";
-	private static final String SIGNAL_AMPLITUDE_TITLE = "Signal Amplitude (mV)";
-	private String detectorName;
-	
-	/**
-	 * 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;
-	}
-	
-	/**
-	 * Sets whether the event display should be cleared after event
-	 * or whether it should retain the previously displayed results.
-	 * @param resetOnUpdate - <code>true</code> means that the event
-	 * display should be cleared on each update and <code>false</code>
-	 * that it should not.
-	 */
-	public void setResetOnUpdate(boolean resetOnUpdate) {
-		this.resetOnUpdate = resetOnUpdate;
-	}
-	
-	/**
-	 * Initializes the single channel monitoring plots for all crystal
-	 * channels and defines the plotter region that contains them.
-	 */
-	@Override
-	public void detectorChanged(Detector detector) {
-	    detectorName=detector.getName();
-		// Reset the AIDA tree directory.
-		aida.tree().cd("/");
-		
-		// Store histograms for the crystals.
-		channelEnergyPlot = new ArrayList<IHistogram1D>(NUM_CHANNELS);
-		channelTimePlot = new ArrayList<IHistogram1D>(NUM_CHANNELS);
-		channelRawWaveform = new ArrayList<IHistogram1D>(NUM_CHANNELS);
-		clusterEnergyPlot = new ArrayList<IHistogram1D>(NUM_CHANNELS);
-		channelTimeVsEnergyPlot = new ArrayList<IHistogram2D>(NUM_CHANNELS);
-		
-		// Create the histograms for single channel energy and time
-		// distribution.
-		for(int ii = 0; ii < NUM_CHANNELS; 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 = EcalMonitoringUtilities.getRowFromHistoID(ii);
-			int column = EcalMonitoringUtilities.getColumnFromHistoID(ii);
-			
-			// Initialize the histograms for the current crystal channel.
-			channelEnergyPlot.add(aida.histogram1D(detectorName + " : "
-						+ inputCollection + " : Hit Energy : " + column + " " + row
-						+ ": " + ii, 100, -0.2, maxEch));
-			channelTimePlot.add(aida.histogram1D(detectorName + " : "
-						+ inputCollection + " : Hit Time : " + column + " " + row + ": "
-						+ ii, 100, 0, 400));     
-			channelTimeVsEnergyPlot.add(aida.histogram2D(detectorName 
-					+ " : " + inputCollection + " : Hit Time Vs Energy : " + column
-					+ " " + row + ": " + ii, 100, 0, 400, 100, -0.2, maxEch));              
-			channelRawWaveform.add(aida.histogram1D(detectorName  + " : "
-					+ inputCollection + " : Hit Energy : " + column + " " + row + ": " + ii));
-			clusterEnergyPlot.add(aida.histogram1D(detectorName  + " : "
-					+ inputCollection + " : Cluster Energy : " + column + " " + row
-					+ ": " + ii, 100, -0.2, maxEch));
-			
-			// 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(RAW_WAVEFORM_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();
-		
-		
+    // 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> clusterEnergyPlot;
+    private ArrayList<IHistogram1D> channelTimePlot;
+    private ArrayList<IHistogram1D> channelRawWaveform;
+    private ArrayList<IHistogram2D> channelTimeVsEnergyPlot;
+
+    // Internal variables.
+    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 boolean resetOnUpdate = true;						 // Clears the event display on each update.
+    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 RAW_WAVEFORM_TITLE = "Raw Waveform";
+    private static final String HIT_ENERGY_TITLE = "Hit Energy (GeV)";
+    private static final String CLUSTER_ENERGY_TITLE = "Cluster Energy (GeV)";
+    private static final String SIGNAL_AMPLITUDE_TITLE = "Signal Amplitude (mV)";
+    private String detectorName;
+
+    /**
+     * 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;
+    }
+
+    /**
+     * Sets whether the event display should be cleared after event
+     * or whether it should retain the previously displayed results.
+     * @param resetOnUpdate - <code>true</code> means that the event
+     * display should be cleared on each update and <code>false</code>
+     * that it should not.
+     */
+    public void setResetOnUpdate(boolean resetOnUpdate) {
+        this.resetOnUpdate = resetOnUpdate;
+    }
+
+    /**
+     * Initializes the single channel monitoring plots for all crystal
+     * channels and defines the plotter region that contains them.
+     */
+    @Override
+    public void detectorChanged(Detector detector) {
+        detectorName=detector.getName();
+        // Reset the AIDA tree directory.
+        aida.tree().cd("/");
+
+        // Store histograms for the crystals.
+        channelEnergyPlot = new ArrayList<IHistogram1D>(NUM_CHANNELS);
+        channelTimePlot = new ArrayList<IHistogram1D>(NUM_CHANNELS);
+        channelRawWaveform = new ArrayList<IHistogram1D>(NUM_CHANNELS);
+        clusterEnergyPlot = new ArrayList<IHistogram1D>(NUM_CHANNELS);
+        channelTimeVsEnergyPlot = new ArrayList<IHistogram2D>(NUM_CHANNELS);
+
+        // Create the histograms for single channel energy and time
+        // distribution.
+        for(int ii = 0; ii < NUM_CHANNELS; 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 = EcalMonitoringUtilities.getRowFromHistoID(ii);
+            int column = EcalMonitoringUtilities.getColumnFromHistoID(ii);
+
+            // Initialize the histograms for the current crystal channel.
+            channelEnergyPlot.add(aida.histogram1D(detectorName + " : "
+                    + inputCollection + " : Hit Energy : " + column + " " + row
+                    + ": " + ii, 100, -0.2, maxEch));
+            channelTimePlot.add(aida.histogram1D(detectorName + " : "
+                    + inputCollection + " : Hit Time : " + column + " " + row + ": "
+                    + ii, 100, 0, 400));     
+            channelTimeVsEnergyPlot.add(aida.histogram2D(detectorName 
+                    + " : " + inputCollection + " : Hit Time Vs Energy : " + column
+                    + " " + row + ": " + ii, 100, 0, 400, 100, -0.2, maxEch));              
+            channelRawWaveform.add(aida.histogram1D(detectorName  + " : "
+                    + inputCollection + " : Hit Energy : " + column + " " + row + ": " + ii));
+            clusterEnergyPlot.add(aida.histogram1D(detectorName  + " : "
+                    + inputCollection + " : Cluster Energy : " + column + " " + row
+                    + ": " + ii, 100, -0.2, maxEch));
+
+            // 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(RAW_WAVEFORM_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();
+
+
 
         int row,column;
         String hName;
@@ -301,263 +302,289 @@
             // 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.
             row = EcalMonitoringUtilities.getRowFromHistoID(ii);
             column = EcalMonitoringUtilities.getColumnFromHistoID(ii);
             hName=detectorName + " : "
                     + inputCollection + " : Hit Energy : " + column + " " + row
                     + ": " + ii;
-            aida.tree().rm(hName);
-           
+            try{
+                aida.tree().rm(hName);
+            }
+            catch(IllegalArgumentException e){
+                System.out.println("Got exception "+e);
+            }
             hName=detectorName + " : "
                     + inputCollection + " : Hit Time : " + column + " " + row + ": "
                     + ii;
-            aida.tree().rm(hName);
-            
+            try{
+                aida.tree().rm(hName);
+            }
+            catch(IllegalArgumentException e){
+                System.out.println("Got exception "+e);
+            }
+
             hName=detectorName+ " : " + inputCollection + " : Hit Time Vs Energy : " + column
                     + " " + row + ": " + ii;
-            aida.tree().rm(hName);
-            
+
+            try{
+                aida.tree().rm(hName);
+            }
+            catch(IllegalArgumentException e){
+                System.out.println("Got exception "+e);
+            }
+
+
             hName=detectorName + " : "
                     + inputCollection + " : Cluster Energy : " + column + " " + row
                     + ": " + ii;
-            aida.tree().rm(hName);
-        
+            try{
+                aida.tree().rm(hName);
+            }
+            catch(IllegalArgumentException e){
+                System.out.println("Got exception "+e);
+            }
+
+
+
             hName=detectorName + " : "
                     + inputCollection + " : Cluster Energy : " + column + " " + row
                     + ": " + ii;
-            aida.tree().rm(hName);
-        
-        
-        }
-      //System.out.println("EcalEventDisplay endOfData clear histograms done");
-		
-		
-	}
-	
-	@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 && resetOnUpdate) { 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 = EcalMonitoringUtilities.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); }
-				}
-			}
-		}
-		
-		// If there are clusters in the event...
-		if (event.hasCollection(Cluster.class, clusterCollection)) {
-			// Get the list of clusters.
-			List<Cluster> clusters = event.get(Cluster.class, clusterCollection);
-			
-			// Iterate over the clusters and add them to the event
-			// display if appropriate.
-			for (Cluster cluster : clusters) {
-				// Get the ix and iy indices for the seed.
-				int ix = cluster.getCalorimeterHits().get(0).getIdentifierFieldValue("ix");
-				int iy = cluster.getCalorimeterHits().get(0).getIdentifierFieldValue("iy");
-				
-				// Get the histogram index for the hit.
-				int id = EcalMonitoringUtilities.getHistoIDFromRowColumn(iy, ix);
-				
-				// Add the cluster energy to the plot.
-				if(cluster.getEnergy() > 0.0) {
-					clusterEnergyPlot.get(id).fill(cluster.getEnergy());
-				}
-				
-				// If an update is needed, add the cluster to the viewer.
-				if(update) { viewer.addCluster(cluster); }
-			}
-		}
-		
-	
-		// 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(!EcalMonitoringUtilities.isInHole(iy, ix)) {
-						// Get the crystal ID for the current hit.
-						int id = EcalMonitoringUtilities.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(event.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 (!EcalMonitoringUtilities.isInHole(ecalPoint.y, ecalPoint.x)) {
-				// Get the crystal ID.
-				int id = EcalMonitoringUtilities.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);
-				
-		
-				// Process and plot the region 3 plot.
-				plotter.region(3).clear();
-				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;
-	}
+
+            try{
+                aida.tree().rm(hName);
+            }
+            catch(IllegalArgumentException e){
+                System.out.println("Got exception "+e);
+            }
+
+        }
+        System.out.println("EcalEventDisplay endOfData clear histograms done");
+    }
+
+    @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 && resetOnUpdate) { 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 = EcalMonitoringUtilities.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); }
+                }
+            }
+        }
+
+        // If there are clusters in the event...
+        if (event.hasCollection(Cluster.class, clusterCollection)) {
+            // Get the list of clusters.
+            List<Cluster> clusters = event.get(Cluster.class, clusterCollection);
+
+            // Iterate over the clusters and add them to the event
+            // display if appropriate.
+            for (Cluster cluster : clusters) {
+                // Get the ix and iy indices for the seed.
+                int ix = cluster.getCalorimeterHits().get(0).getIdentifierFieldValue("ix");
+                int iy = cluster.getCalorimeterHits().get(0).getIdentifierFieldValue("iy");
+
+                // Get the histogram index for the hit.
+                int id = EcalMonitoringUtilities.getHistoIDFromRowColumn(iy, ix);
+
+                // Add the cluster energy to the plot.
+                if(cluster.getEnergy() > 0.0) {
+                    clusterEnergyPlot.get(id).fill(cluster.getEnergy());
+                }
+
+                // If an update is needed, add the cluster to the viewer.
+                if(update) { viewer.addCluster(cluster); }
+            }
+        }
+
+
+        // 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(!EcalMonitoringUtilities.isInHole(iy, ix)) {
+                        // Get the crystal ID for the current hit.
+                        int id = EcalMonitoringUtilities.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(event.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 (!EcalMonitoringUtilities.isInHole(ecalPoint.y, ecalPoint.x)) {
+                // Get the crystal ID.
+                int id = EcalMonitoringUtilities.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);
+
+
+                // Process and plot the region 3 plot.
+                plotter.region(3).clear();
+                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;
+    }
 }

Modified: java/trunk/monitoring-drivers/src/main/java/org/hps/monitoring/ecal/plots/EcalLedSequenceMonitor.java
 =============================================================================
--- java/trunk/monitoring-drivers/src/main/java/org/hps/monitoring/ecal/plots/EcalLedSequenceMonitor.java	(original)
+++ java/trunk/monitoring-drivers/src/main/java/org/hps/monitoring/ecal/plots/EcalLedSequenceMonitor.java	Tue Oct 27 11:33:16 2015
@@ -58,794 +58,814 @@
  */
 public class EcalLedSequenceMonitor extends Driver{
 
-	private static final int NUM_CHANNELS = 11 * 47;
-	private static final String dbTag = "led";
-	private static final String dbTableName = "ecal_led_calibrations";
-	private static final int runNumberMax = 9999;
-	private static final int nDrivers = 8;
-	private static final int nSteps = 56;
-
-	String inputCollectionRaw = "EcalReadoutHits";
-	String inputCollection = "EcalCalHits";	
-	AIDA aida;
-
-	DatabaseConditionsManager conditionsManager;
-
-	private EcalChannelCollection ChannelCollection;	
-	private EcalLedCollection LedCollection;
-	private EcalConditions ecalConditions;
-
-	Map < Integer,Integer > LedTopMap; //chid (conditions) --> LED id
-	Map < Integer,Integer > LedBotMap; //chid (conditions) --> LED id 
-
-	Map < Integer,Integer > LedTopMapInverted; //LED id --> chid (conditions)
-	Map < Integer,Integer > LedBotMapInverted; //LED id  --> chid (conditions)
-
-	private boolean useRawEnergy=false;
-
-	String outFileName;
-
-
-	private int runNumber = 0;	
-	private int eventN    = 0;
-	private int id,row,column,chid,ledid,driverid;
-	private  int[][] LEDStep = new int[][]{
-			//first 4 are the flasher1 sequence, TOP controller 
-			{2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,-1,-1},
-			{56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111},
-			{112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,-1}, //missing 135 is ok
-			{168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223},
-			//second 4 are the flasher2 sequence, BOTTOM controller 
-			{2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,-1,-1},	
-			{56,57,58,59,60,61,62,63,64,65,66,67,68,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,-1}, //missing 69 is OK
-			{112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167},	
-			{168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223},
-	};
-
-	private int[] iStep = new int[nDrivers];
-	private int[] nEvents = new int[NUM_CHANNELS];
-	private double[] mMean = new double[NUM_CHANNELS];
-	private double[] mRMS = new double[NUM_CHANNELS];
-
-	private int nEventsMin=200;
-	private int nMinChannelsWithEvents=350; 
-	private double energy,fillEnergy,fillTime;
-	private double energyCut=2; //we expect very high energy from the LEDs..
-	private double skipInitial=0.05;
-	private double skipMin=0.3;
-	private long cellID;
-
-
-
-
-	//Histograms-functions-ntuples
-	private ArrayList<ITuple> iTuple;
-
-	private IFunction  fFunction,fFunction1;
-	private IProfile1D   cProfile;
-	private IHistogram2D			hMeanCharge2D;
-	private ArrayList<IHistogram1D> hCharge;
-	private ArrayList<IHistogram2D> hChargeVsEvn;
-	private IPlotterFactory factory;
-	private IPlotter pPlotter=null;
-	private IPlotter pPlotter2=null;
-	private IPlotterStyle style ;
-	private int[] fitStatus = new int[NUM_CHANNELS];
-
-	private boolean doFullAnalysis=false;
-	private boolean isMonitoringApp=false; 
-
-	private double[] fPars;    
-	private double[] fPrevPars;
-	private double[] fParErrs;
-	private String[] fParNames; 
-
-
-	private double fEvnMinDraw=0.;
-	private double fEvnMaxDraw=80000.;
-	private double fChargeMinDraw=0.;
-	private double fChargeMaxDraw=100.;
-
-	/*Components for user interaction*/
-	private JDialog dialog;
-	private JLabel  label;
-	private JFrame frame;
-	private JPanel panel;
-	String  labelString;
-	private JButton okButton,cancelButton;
-	private int m_iteration=0;
-	private int m_ret=0;
-	static Object modalMonitor = new Object();
-
-	public void setUseRawEnergy(boolean useRawEnergy) {
-		this.useRawEnergy=useRawEnergy;
-	}
-
-	public void setEnergyCut(double energyCut) {
-		this.energyCut=energyCut;
-	}
-	public void setSkipInitial(double skipInitial) {
-		this.skipInitial=skipInitial;
-	}
-	public void setSkipMin(double skipMin) {
-		this.skipMin=skipMin;
-	}
-
-	public void setEvnMinDraw(double evnMinDraw){
-		this.fEvnMinDraw=evnMinDraw;
-	}
-	public void setEvnMaxDraw(double evnMaxDraw){
-		this.fEvnMaxDraw=evnMaxDraw;
-	}
-	public void setChargeMinDraw(double chargeMinDraw){
-		this.fChargeMinDraw=chargeMinDraw;
-	}
-	public void setChargeMaxDraw(double chargeMaxDraw){
-		this.fChargeMaxDraw=chargeMaxDraw;
-	}
-
-	public void setNEventsMin(int nEeventsMin){
-		this.nEventsMin=nEventsMin;
-	}
-
-	public void setIsMonitoringApp(boolean app){
-		this.isMonitoringApp=app;
-	}
-
-	public void setDoFullAnalysis(boolean fullAnalysis){
-		this.doFullAnalysis=fullAnalysis;
-	}
-
-	@Override
-	protected void detectorChanged(Detector detector) {
-		System.out.println("LedAnalysis::Detector changed was called");
-		System.out.println(fEvnMinDraw+" "+fEvnMaxDraw);
-		for (int ii=0;ii<nDrivers;ii++){
-			iStep[ii]=-1;
-		}
-
-		// Setup conditions
-
-		conditionsManager = DatabaseConditionsManager.getInstance();
-
-		LedTopMap = new HashMap< Integer , Integer >(); //key: ecal channel ID. Value:  led id
-		LedBotMap = new HashMap< Integer , Integer >();	
-
-		LedTopMapInverted = new HashMap< Integer , Integer >(); //key: led id. Value: ecal channel id
-		LedBotMapInverted = new HashMap< Integer , Integer >(); 
-
-
-		ChannelCollection = conditionsManager.getCachedConditions(EcalChannelCollection.class, "ecal_channels").getCachedData();	
-		LedCollection = conditionsManager.getCachedConditions(EcalLedCollection.class, "ecal_leds").getCachedData();
-		ecalConditions = conditionsManager.getEcalConditions();		
-
-		for (EcalChannel channel : ChannelCollection){
-			chid = channel.getChannelId();
-			for (EcalLed Led : LedCollection) {    	
-				if (Led.getEcalChannelId()==chid){
-					if (channel.getY()>0){
-						LedTopMap.put( chid , Led.getLedNumber() );
-						LedTopMapInverted.put(  Led.getLedNumber(), chid  );
-					}
-					else if (channel.getY()<0){
-						LedBotMap.put( chid , Led.getLedNumber() );
-						LedBotMapInverted.put( Led.getLedNumber(), chid );                    
-					}
-				}
-			}
-		}
-
-
-
-		// Setup plots
-		aida = AIDA.defaultInstance();
-		aida.tree().cd("/");
-		hMeanCharge2D = aida.histogram2D("Average LED response", 47, -23.5, 23.5, 11, -5.5, 5.5);
-
-		factory= aida.analysisFactory().createPlotterFactory("Ecal Led Sequence");
-		pPlotter= factory.create("Drivers");
-		pPlotter.createRegions(4,2);
-		if (isMonitoringApp){
-			pPlotter2=factory.create("Sequence Map");
-			pPlotter2.createRegions(1,1);
-			pPlotter2.region(0).plot(hMeanCharge2D);
-		}   
-		iTuple = new ArrayList<ITuple>(NUM_CHANNELS);   
-		hCharge = new ArrayList<IHistogram1D>(NUM_CHANNELS);
-		hChargeVsEvn = new ArrayList<IHistogram2D>(nDrivers);
-
-
-
-		//pPlotter2.region(0).plot(hMeanCharge2D);
-
-		for (int ii=0;ii<NUM_CHANNELS;ii++){
-			int row = EcalMonitoringUtilities.getRowFromHistoID(ii);
-			int column = EcalMonitoringUtilities.getColumnFromHistoID(ii);	    
-			iTuple.add(aida.analysisFactory().createTupleFactory(aida.tree()).create("nTuple"+ii,"nTuple"+ii,"int fEvn=0 , double fCharge=0.,double fTime=0.",""));
-		}
-
-		for (int ii=0;ii<nDrivers;ii++){
-			hChargeVsEvn.add(aida.histogram2D("Driver"+ii,100,fEvnMinDraw,fEvnMaxDraw,100,fChargeMinDraw,fChargeMaxDraw));
-			pPlotter.region(ii).plot( hChargeVsEvn.get(ii));
-		}
-
-		pPlotter.show();
-		if (isMonitoringApp) pPlotter2.show();
-
-	}		
-
-	@Override
-	public void process(EventHeader event) {
-		runNumber = event.getRunNumber();
-		eventN++;
-		if (event.hasCollection(CalorimeterHit.class, inputCollection)) {
-			//List<BassRawCalorimeterHit> hits = event.get(BaseRawCalorimeterHit.class, inputCollectionRaw);
-			List<CalorimeterHit> hits = event.get(CalorimeterHit.class, inputCollection);
-			for (CalorimeterHit hit : hits) {
-
-				column = hit.getIdentifierFieldValue("ix");
-				row = hit.getIdentifierFieldValue("iy");
-				id = EcalMonitoringUtilities.getHistoIDFromRowColumn(row, column);
-				cellID=hit.getCellID();        
-				chid = ChannelCollection.findGeometric(cellID).getChannelId();
-
-				energy = hit.getCorrectedEnergy();
-				if (useRawEnergy){
-					fillEnergy = getRawADCSum(energy,cellID);
-				}
-				else {
-					fillEnergy = energy;
-				}
-				fillTime = hit.getTime();
-
-
-				//find the LED
-				if (row>0){
-					ledid=LedTopMap.get(chid);
-				}
-				else if (row<0){
-					ledid=LedBotMap.get(chid);
-				}
-				driverid=getDriver(ledid);
-				if (row<0) driverid+=4;
-
-
-
-				/*Skip the events under thr*/
-				if (energy<energyCut) continue;
-
-				/*First, check if this led is the one in the NEXT step. Therefore, increment by 1 the step*/
-				if (iStep[driverid]<(nSteps-1)){
-					if (ledid==LEDStep[driverid][iStep[driverid]+1]){   
-						iStep[driverid]++;
-						System.out.println("LedAnalysis:: increment step ("+iStep[driverid]+") for driver "+driverid+" . Led ID: "+ledid+" Column: "+column+" Row: "+row);
-						if (iStep[driverid]>0) drawProfiles(LEDStep[driverid][iStep[driverid]-1],driverid);      
-					}	
-				}
-
-
-				if (iStep[driverid]==-1) continue;
-
-				/*Put this code here, since we want to always fill the ntuple*/
-				iTuple.get(id).fill(0,nEvents[id]);
-				iTuple.get(id).fill(1,fillEnergy);
-				iTuple.get(id).fill(2,fillTime);
-				iTuple.get(id).addRow();
-				nEvents[id]++;
-
-				/*Case 1: this led is the one in the corresponding step*/;
-				if (ledid==LEDStep[driverid][iStep[driverid]]){
-
-				}
-				else{	/*Case 2: this led is not one in the corresponding step (but maybe is the neighborhood??Ctalk??)*/;
-
-				}
-
-				/*Add a debug print */
-				if (eventN % 10000==0){
-					System.out.println("Debug. LED ID: "+ledid+" DRIVER ID: "+driverid+" ECAL ID: "+id+" ROW: "+row+" COLUMN: "+column+ "HISTO ID: "+id);
-				}
-			}
-			if (eventN % 10000==0){
-				System.out.println("\n");
-			}
-		}		
-	}
-
-	/*
-	 * The endOfData() method analises each ntuple to find the LED response.
-	 * We cannot simply fit a gaussian to the energy distribution, since there is a high-energy tail due to the LED being turned on:
-	 * When the LED turns on, it is "cold", and emits more light. Immediately, it starts to heat, and due to temperature effects the
-	 * emitted light is less. This is clearly visible if one plots the charge VS the event number: the trend is decreasing, toward a
-	 * plateau, that corresponds to the value at thermal equilibrium.
-	 * 
-	 * For (few) channels, the first charge values are close to 0, then charge grows rapidly, then it returns back to the plateau.
-	 * To handle these, I always cut the first 10% events
-	 * To properly handle this:
-	 * 
-	 * 1) First create a profile histogram, charge VS event number.
-	 * 2) Fit it with something like "A*exp(-event_number/N0)+C. The function does not need to be extra-accurate at this stage
-	 * 3) Cut the events with event_number < 5*N0.
-	 * 4) Fit the remaining events with a gaussian.
-	 */
-	@Override
-	public void endOfData() {
-		System.out.println("LedAnalysis::end of data");
-		System.out.println("LedAnalysis:: nEventsMin is: "+nEventsMin);
-
-		double e,eMin,eMax;
-		double t;
-		int n,nBins,nFits,nSkip;
-
-		int row, column;
-
-		String hName; 
-		IFunctionFactory fFactory=aida.analysisFactory().createFunctionFactory(aida.tree());
-
-		IFitResult fResult;
-		IFitter	   fFitter;
-
-		for (int id = 0; id < 11 * 47; id++) {
-
-			eMin=9999;
-			eMax=-9999;
-			row = EcalMonitoringUtilities.getRowFromHistoID(id);
-			column = EcalMonitoringUtilities.getColumnFromHistoID(id);
-			System.out.println("");
-			System.out.println("Doing channel: X= "+column+" Y= "+row);
-			System.out.println("Number of entries in analysis ntuple: "+iTuple.get(id).rows());
-			System.out.println("Number of recognized events: "+nEvents[id]);
-			/*Create the profile. Create it for all the channels, to keep sync.*/
-			nBins=nEvents[id]/100;
-			if (nBins<=0) nBins=1;
-
-			/*Clear previous*/
-
-			if (id>0){
-				aida.tree().rm("strip");
-				aida.tree().rm("fun0");
-				aida.tree().rm("fun1");
-			}
-			/*Create the profile.*/
-			cProfile=aida.profile1D("strip",nBins,-0.5,nEvents[id]*(1-skipInitial)+0.5);
-			cProfile.reset();
-			/*Create the function for the profile fit and the gaus fit*/
-			fFunction=fFactory.createFunctionFromScript("fun0",1,"A*exp(-x[0]/tau)+B","A,tau,B","",null);
-			fFunction1=fFactory.createFunctionByName("fun1","G");
-
-			if (EcalMonitoringUtilities.isInHole(row,column)==true){
-				System.out.println("Channel X= "+column+" Y= "+row+" is in hole. Skip");
-				hCharge.add(aida.histogram1D("charge_"+id,200,0.,1.)); //create here the histogram to keep sync
-				System.out.println("In hole, skip");
-				continue;
-			}
-			else if (nEvents[id]<nEventsMin) {
-				hCharge.add(aida.histogram1D("charge_"+id,200,0.,1.)); //create here the histogram to keep sync
-				System.err.println("LedAnalysis:: the channel X= "+column+" Y= "+row+" has not enough events "+nEvents[id]+" "+nEventsMin);
-
-				continue;
-			}			  
-
-			//Fill the profile*/
-			nSkip=(int)(nEvents[id]*skipInitial);
-			if (nSkip>iTuple.get(id).rows()){
-				System.out.println("Can't skip initial events?");
-				nSkip=0;
-			}
-			iTuple.get(id).start();
-			iTuple.get(id).skip(nSkip); //This is the work-around for those channels with charge starting from 0 and rapidly growing//
-			n=0;
-			iTuple.get(id).next(); 
-			while ( iTuple.get(id).next() ){
-				e=iTuple.get(id).getDouble(1);
-				if (e<eMin) eMin=e;           			  
-				if (e>eMax) eMax=e;
-				cProfile.fill(1.*n,e);
-				n++;
-			}			
-			fFitter=aida.analysisFactory().createFitFactory().createFitter("chi2","","v");
-
-			if (doFullAnalysis){ 
-				//Init function parameters
-				double[] initialPars={eMax-eMin,nEvents[id]/10.,eMin};
-				if (initialPars[0]<0) initialPars[0]=0;
-				fFunction.setParameters(initialPars);
-
-				//Do the fit      
-				System.out.println("LedAnalysis:: do profile fit "+id+" "+fFitter.engineName()+" "+fFitter.fitMethodName());
-				System.out.println("LedAnalysis:: initial parameters "+initialPars[0]+" "+initialPars[1]+" "+initialPars[2]);
-				fResult=fFitter.fit(cProfile,fFunction);
-				fPars     = fResult.fittedParameters();
-				fParErrs  = fResult.errors();
-				fParNames = fResult.fittedParameterNames();			
-				System.out.println("LedAnalysis:: Status= "+fResult.fitStatus()+" "+fResult.isValid()+" Chi2 = "+fResult.quality()+" NDF: "+fResult.ndf());
-				for(int i=0; i< fResult.fittedFunction().numberOfParameters(); i++ ){
-					System.out.println(fParNames[i]+" : "+fPars[i]+" +- "+fParErrs[i]);
-				}  
-				fFunction.setParameters(fPars);
-
-
-				//Do again the fit: it is a terrible work-around
-				nFits=0;
-				if (Double.isNaN(fParErrs[1])){
-					fPars=fPrevPars;
-				}
-				while (Double.isNaN(fParErrs[1])){
-					System.out.println("LedAnalysis:: redo fit");
-					fFunction.setParameters(fPars);
-					fResult=fFitter.fit(cProfile,fFunction);
-					fPars     = fResult.fittedParameters();
-					fParErrs  = fResult.errors();
-					System.out.println("LedAnalysis:: Status= "+fResult.fitStatus()+" "+fResult.isValid()+" Chi2 = "+fResult.quality()+" NDF: "+fResult.ndf());
-					for(int i=0; i< fResult.fittedFunction().numberOfParameters(); i++ ){
-						System.out.println(fParNames[i]+" : "+fPars[i]+" +- "+fParErrs[i]);
-					}  
-					fFunction.setParameters(fPars);
-					nFits++;
-					if (nFits>=10){
-						System.out.println("LedAnalysis:: Error, too many fits without convergence");
-						break;
-					}
-				}
-				fPrevPars=Arrays.copyOf(fPars,fPars.length);
-				System.out.println("LedAnalysis:: fit "+id+" done");  
-
-				//Now we have the tau parameter. Take ONLY the events that are with N>5*tau/
-				//As a cross-check, also verify that tau > Nevents/10, otherwise skip the first Nevents/2
-				//and emit warning
-				nSkip=(int)( fPars[1]*5);
-				if (nSkip < (nEvents[id]*skipMin)){
-					System.out.println("LedAnalysis:: Skip number too low: "+nSkip+" Increment it to "+nEvents[id]/2);
-					nSkip=(int)(nEvents[id]*skipMin);
-				}
-				if (nSkip > nEvents[id]){
-					System.out.println("LedAnalysis:: Skip number too high, reduce it");
-					nSkip=(int)(nEvents[id]*skipMin);
-				}
-
-			}
-			else{
-				nSkip=(int)(nEvents[id]*(skipMin+skipInitial));
-			}
-
-			System.out.println("LedAnalysis:: gaus fit :: Going to skip "+nSkip+" out of "+nEvents[id]);
-			System.out.println("eMin is: "+eMin+" eMax is: "+eMax);
-			hCharge.add(aida.histogram1D("charge_"+id,200,eMin*0.9,eMax*1.1));
-
-
-			iTuple.get(id).start();
-			iTuple.get(id).skip(nSkip); 
-			n=0;
-			while (iTuple.get(id).next()){
-				e=iTuple.get(id).getDouble(1);
-				t=iTuple.get(id).getDouble(2);
-				hCharge.get(id).fill(e);
-				n++;
-			}			
-
-			/*Finally do the fit with the gaussian*/
-			double[] initialPars1={hCharge.get(id).maxBinHeight(),hCharge.get(id).mean(),hCharge.get(id).rms()};
-
-			System.out.println("LedAnalysis:: Gaus fit");
-			System.out.println("LedAnalysis:: initial parameters "+initialPars1[0]+" "+initialPars1[1]+" "+initialPars1[2]);
-
-			fFunction1.setParameters(initialPars1);
-			fResult=fFitter.fit(hCharge.get(id),fFunction1);
-			fPars     = fResult.fittedParameters();
-			fParErrs  = fResult.errors();
-			fParNames = fResult.fittedParameterNames();			
-			System.out.println("Status= "+fResult.fitStatus()+" "+fResult.isValid()+" Chi2 = "+fResult.quality()+" NDF: "+fResult.ndf());
-			for(int i=0; i< fResult.fittedFunction().numberOfParameters(); i++ ){
-				System.out.println(fParNames[i]+" : "+fPars[i]+" +- "+fParErrs[i]);
-			}  
-			fFunction1.setParameters(fPars);
-			mMean[id]=fPars[1];
-			mRMS[id]=fPars[2];
-
-			hMeanCharge2D.fill(column,row,mMean[id]);
-			System.out.println("\n");
-		}//End loop on channels
-
-
-
-		if ((pPlotter2!=null)&&(isMonitoringApp)){
-			style = pPlotter2.region(0).style();
-			style.setParameter("hist2DStyle", "colorMap");
-			style.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
-			style.dataStyle().fillStyle().setParameter("showZeroHeightBins", Boolean.FALSE.toString()); 
-			pPlotter2.region(0).plot(hMeanCharge2D);
-			pPlotter2.region(0).refresh();
-		}
-		else{
-			IPlotterStyle pstyle =  aida.analysisFactory().createPlotterFactory().createPlotterStyle();
-			pPlotter2 = null;
-			pPlotter2 =  aida.analysisFactory().createPlotterFactory().create();
-			pstyle.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
-			pstyle.dataStyle().fillStyle().setParameter("showZeroHeightBins", Boolean.FALSE.toString());
-			pstyle.setParameter("hist2DStyle", "colorMap");
-			if (pPlotter2!=null){
-				pPlotter2.createRegion().plot(hMeanCharge2D,pstyle);
-				pPlotter2.show();
-			}
-		}
-
-
-		askUploadToDBDialog();
-		synchronized (modalMonitor) {
-			try{
-				modalMonitor.wait(120000); //wait 2 minutes for user interaction.
-			}
-			catch(InterruptedException excp){
-				System.out.println("Got exception: "+excp);
-			}
-		}
-		if (m_ret==1){
-			System.out.println("OK, upload to DB");
-			try {
-				uploadToDB();
-			} catch (SQLException | DatabaseObjectException | ConditionsObjectException error) {
-				throw new RuntimeException("Error uploading to the database.", error);
-			}
-			if (isMonitoringApp){
-				System.out.println("Save an Elog too");
-				uploadToElog();
-			}
-		}
-
-		/*Write a file with the LED values*/
-		try {
-			if (useRawEnergy){
-				outFileName=runNumber+".raw.txt";
-			}
-			else{
-				outFileName=runNumber+".energy.txt";
-			}
-			PrintWriter writer = new PrintWriter(outFileName, "UTF-8");
-
-
-			for (int id = 0; id < 11 * 47; id++) {
-
-				row = EcalMonitoringUtilities.getRowFromHistoID(id);
-				column = EcalMonitoringUtilities.getColumnFromHistoID(id);
-				if (EcalMonitoringUtilities.isInHole(row, column)) continue;
-				if ((row == 0) || (column == 0)) continue;
-
-				writer.print(column+" "+row+" "+" "+ mMean[id]+" "+mRMS[id]+"\r\n");
-
-			}
-			writer.close();
-
-		} 
-		catch (FileNotFoundException fnfe) {
-
-			System.out.println(fnfe.getMessage());
-
-		}
-
-		catch (IOException ioe) {
-
-			System.out.println(ioe.getMessage());
-
-		}
-
-
-		System.out.println("EcalLedSequenceMonitor endOfData clear histograms"); 
-		for(int ii = 0; ii < NUM_CHANNELS; ii++) {   	
-			row=EcalMonitoringUtilities.getRowFromHistoID(ii);
-			column = EcalMonitoringUtilities.getColumnFromHistoID(ii);      	  
-			hName="charge_"+ii;	 
-			aida.tree().rm(hName);
-			/*aida.tree().add(iTuple.get(ii));*/
-		}
-		System.out.println("EcalLedSequenceMonitor endOfData clear histograms done");   
-		System.out.println("endOfData end");
-		System.out.println("The program is not stucked. It is writing the output AIDA file, this takes time!");
-	}/*End endOfData*/
-
-
-	/**
-	 * This function returns the driver number (from 0 to 3) given the LED id.
-	 * @param led
-	 * @return
-	 */
-	public int getDriver(int led){
-		int ret=-1;	
-		if ((led>=2)&&(led<56)) ret=0;
-		else if ((led>=56)&&(led<112)) ret=1;
-		else if ((led>=112)&&(led<168)) ret=2;
-		else if ((led>=168)&&(led<224)) ret=3;
-		return ret;
-	}
-
-	/**
-	 * Very simple method to retreive the pedestal-subtracted raw Energy.
-	 * If the gain changes (because we do a re-calibration), I do not want to include this in the LED analysis
-	 * @param energy
-	 * @param cellID
-	 * @return
-	 */
-	public double getRawADCSum(double energy,long cellID){
-		EcalChannelConstants channelData = ecalConditions.getChannelConstants(ecalConditions.getChannelCollection().findGeometric(cellID));
-		double RawSum=energy / EcalUtils.GeV;
-		double gain=channelData.getGain().getGain();
-		double ret=RawSum/gain;
-		//  System.out.println("A:C "+RawSum+" "+ret);
-		return ret;
-	}
-
-	private void uploadToDB() throws DatabaseObjectException, ConditionsObjectException, SQLException {
-		int x,y,id;
-		double mean,rms;
-		System.out.println(String.format("Uploading new led data to the database, runMin=%d, runMax=%d, tag=%s ....",
-				runNumber,runNumberMax,dbTag));
-
-		EcalLedCalibrationCollection led_calibrations =  new EcalLedCalibrationCollection();
-
-		TableMetaData tableMetaData = conditionsManager.findTableMetaData(dbTableName);
-		led_calibrations.setTableMetaData(tableMetaData);
-
-		for (int cid = 1; cid <= 442; cid++) {/*This is a loop over the channel ID, as in the conditions system*/
-			EcalChannel cc = findChannel(cid);
-			x = cc.getX(); //This is the column
-			y = cc.getY(); //This is the row
-			id=EcalMonitoringUtilities.getHistoIDFromRowColumn(y,x);
-			mean=mMean[id];
-			rms=mRMS[id];
-			led_calibrations.add(new EcalLedCalibration(cid,mean,rms));
-		}
-
-		int collectionId = -1;
-
-		try {
-			collectionId = conditionsManager.getCollectionId(led_calibrations, "loaded by EcalLedSequenceMonitor");
-		} catch (Exception e) {
-			throw new RuntimeException(e);
-		}
-		System.err.println("CollectionID:  "+collectionId);
-		led_calibrations.insert();
-		ConditionsRecord conditionsRecord = new ConditionsRecord(
-				led_calibrations.getCollectionId(), runNumber, runNumberMax, dbTableName, dbTableName, 
-				"Generated by LedAnalysis from Run #"+runNumber, dbTag);
-		conditionsRecord.insert();
-
-		System.out.println("Upload to DB done");
-	}
-
-	private void uploadToElog(){
-		String path,exe,command,imgpath;
-		path="/home/hpsrun/LedSequenceData";
-		exe=path+"/doElog.csh";
-		imgpath=path+"/screenshots/"+runNumber+".png";
-
-		File f=new File(path);
-		if (!f.exists()){
-			System.err.println("LedMonitoringSequence:: wrong path");
-			return;
-		}
-		if (pPlotter2==null){
-			System.err.println("LedMonitoringSquence:: no plotter");
-			return;
-		}
-		try{
-			pPlotter2.writeToFile(imgpath);
-		}
-		catch(Exception e){
-			System.err.println("Exception "+e);
-		}
-		File f1=new File(exe);
-		if (!f1.exists()){
-			System.err.println("LedMonitoringSequence:: no script!");
-			return;
-		}   
-		command=exe+" "+imgpath;
-		try{
-			System.out.println("LedMonitoringSequence:: try this command: "+command);
-			Runtime.getRuntime().exec(command);
-		}
-		catch(Exception e){
-			System.err.println("Exception "+e);
-		}
-	}
-
-
-	private void drawProfiles(int ledID,int driverID){
-
-		int m_column,m_row,m_ledID,m_chID,m_ID,m_driverID;
-
-		m_ledID = ledID;
-		m_driverID = driverID;
-		m_chID = 0;
-
-
-		if (m_driverID<=3) m_chID = LedTopMapInverted.get(ledID);
-		else m_chID = LedBotMapInverted.get(ledID);
-
-		m_column=findChannel(m_chID).getX();
-		m_row=findChannel(m_chID).getY();
-		m_ID=EcalMonitoringUtilities.getHistoIDFromRowColumn(m_row, m_column);
-		/* 
+    private static final int NUM_CHANNELS = 11 * 47;
+    private static final String dbTag = "led";
+    private static final String dbTableName = "ecal_led_calibrations";
+    private static final int runNumberMax = 9999;
+    private static final int nDrivers = 8;
+    private static final int nSteps = 56;
+
+    String inputCollectionRaw = "EcalReadoutHits";
+    String inputCollection = "EcalCalHits";	
+    AIDA aida;
+
+    DatabaseConditionsManager conditionsManager;
+
+    private EcalChannelCollection ChannelCollection;	
+    private EcalLedCollection LedCollection;
+    private EcalConditions ecalConditions;
+
+    Map < Integer,Integer > LedTopMap; //chid (conditions) --> LED id
+    Map < Integer,Integer > LedBotMap; //chid (conditions) --> LED id 
+
+    Map < Integer,Integer > LedTopMapInverted; //LED id --> chid (conditions)
+    Map < Integer,Integer > LedBotMapInverted; //LED id  --> chid (conditions)
+
+    private boolean useRawEnergy=false;
+
+    String outFileName;
+
+
+    private int runNumber = 0;	
+    private int eventN    = 0;
+    private int id,row,column,chid,ledid,driverid;
+    private  int[][] LEDStep = new int[][]{
+            //first 4 are the flasher1 sequence, TOP controller 
+            {2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,-1,-1},
+            {56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111},
+            {112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,-1}, //missing 135 is ok
+            {168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223},
+            //second 4 are the flasher2 sequence, BOTTOM controller 
+            {2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,-1,-1},	
+            {56,57,58,59,60,61,62,63,64,65,66,67,68,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,-1}, //missing 69 is OK
+            {112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167},	
+            {168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223},
+    };
+
+    private int[] iStep = new int[nDrivers];
+    private int[] nEvents = new int[NUM_CHANNELS];
+    private double[] mMean = new double[NUM_CHANNELS];
+    private double[] mRMS = new double[NUM_CHANNELS];
+
+    private int nEventsMin=200;
+    private int nMinChannelsWithEvents=350; 
+    private double energy,fillEnergy,fillTime;
+    private double energyCut=2; //we expect very high energy from the LEDs..
+    private double skipInitial=0.05;
+    private double skipMin=0.3;
+    private long cellID;
+
+
+
+
+    //Histograms-functions-ntuples
+    private ArrayList<ITuple> iTuple;
+
+    private IFunction  fFunction,fFunction1;
+    private IProfile1D   cProfile;
+    private IHistogram2D			hMeanCharge2D;
+    private ArrayList<IHistogram1D> hCharge;
+    private ArrayList<IHistogram2D> hChargeVsEvn;
+    private IPlotterFactory factory;
+    private IPlotter pPlotter=null;
+    private IPlotter pPlotter2=null;
+    private IPlotterStyle style ;
+    private int[] fitStatus = new int[NUM_CHANNELS];
+
+    private boolean doFullAnalysis=false;
+    private boolean isMonitoringApp=false; 
+    private boolean saveTuple=false; 
+
+    private double[] fPars;    
+    private double[] fPrevPars;
+    private double[] fParErrs;
+    private String[] fParNames; 
+
+
+    private double fEvnMinDraw=0.;
+    private double fEvnMaxDraw=80000.;
+    private double fChargeMinDraw=0.;
+    private double fChargeMaxDraw=100.;
+
+    /*Components for user interaction*/
+    private JDialog dialog;
+    private JLabel  label;
+    private JFrame frame;
+    private JPanel panel;
+    String  labelString;
+    private JButton okButton,cancelButton;
+    private int m_iteration=0;
+    private int m_ret=0;
+    static Object modalMonitor = new Object();
+
+    public void setUseRawEnergy(boolean useRawEnergy) {
+        this.useRawEnergy=useRawEnergy;
+    }
+
+    public void setEnergyCut(double energyCut) {
+        this.energyCut=energyCut;
+    }
+    public void setSkipInitial(double skipInitial) {
+        this.skipInitial=skipInitial;
+    }
+    public void setSkipMin(double skipMin) {
+        this.skipMin=skipMin;
+    }
+
+    public void setEvnMinDraw(double evnMinDraw){
+        this.fEvnMinDraw=evnMinDraw;
+    }
+    public void setEvnMaxDraw(double evnMaxDraw){
+        this.fEvnMaxDraw=evnMaxDraw;
+    }
+    public void setChargeMinDraw(double chargeMinDraw){
+        this.fChargeMinDraw=chargeMinDraw;
+    }
+    public void setChargeMaxDraw(double chargeMaxDraw){
+        this.fChargeMaxDraw=chargeMaxDraw;
+    }
+
+    public void setNEventsMin(int nEeventsMin){
+        this.nEventsMin=nEventsMin;
+    }
+
+    public void setIsMonitoringApp(boolean app){
+        this.isMonitoringApp=app;
+    }
+
+    public void setDoFullAnalysis(boolean fullAnalysis){
+        this.doFullAnalysis=fullAnalysis;
+    }
+
+    public void setSaveTuple(boolean flag){
+        this.saveTuple=flag;
+    }
+
+    @Override
+    protected void detectorChanged(Detector detector) {
+        System.out.println("LedAnalysis::Detector changed was called");
+        System.out.println(fEvnMinDraw+" "+fEvnMaxDraw);
+        for (int ii=0;ii<nDrivers;ii++){
+            iStep[ii]=-1;
+        }
+
+        // Setup conditions
+
+        conditionsManager = DatabaseConditionsManager.getInstance();
+
+        LedTopMap = new HashMap< Integer , Integer >(); //key: ecal channel ID. Value:  led id
+        LedBotMap = new HashMap< Integer , Integer >();	
+
+        LedTopMapInverted = new HashMap< Integer , Integer >(); //key: led id. Value: ecal channel id
+        LedBotMapInverted = new HashMap< Integer , Integer >(); 
+
+
+        ChannelCollection = conditionsManager.getCachedConditions(EcalChannelCollection.class, "ecal_channels").getCachedData();	
+        LedCollection = conditionsManager.getCachedConditions(EcalLedCollection.class, "ecal_leds").getCachedData();
+        ecalConditions = conditionsManager.getEcalConditions();		
+
+        for (EcalChannel channel : ChannelCollection){
+            chid = channel.getChannelId();
+            for (EcalLed Led : LedCollection) {    	
+                if (Led.getEcalChannelId()==chid){
+                    if (channel.getY()>0){
+                        LedTopMap.put( chid , Led.getLedNumber() );
+                        LedTopMapInverted.put(  Led.getLedNumber(), chid  );
+                    }
+                    else if (channel.getY()<0){
+                        LedBotMap.put( chid , Led.getLedNumber() );
+                        LedBotMapInverted.put( Led.getLedNumber(), chid );                    
+                    }
+                }
+            }
+        }
+
+
+
+        // Setup plots
+        aida = AIDA.defaultInstance();
+        aida.tree().cd("/");
+        hMeanCharge2D = aida.histogram2D("Average LED response", 47, -23.5, 23.5, 11, -5.5, 5.5);
+
+        factory= aida.analysisFactory().createPlotterFactory("Ecal Led Sequence");
+        pPlotter= factory.create("Drivers");
+        pPlotter.createRegions(4,2);
+        if (isMonitoringApp){
+            pPlotter2=factory.create("Sequence Map");
+            pPlotter2.createRegions(1,1);
+            pPlotter2.region(0).plot(hMeanCharge2D);
+        }   
+        iTuple = new ArrayList<ITuple>(NUM_CHANNELS);   
+        hCharge = new ArrayList<IHistogram1D>(NUM_CHANNELS);
+        hChargeVsEvn = new ArrayList<IHistogram2D>(nDrivers);
+
+
+
+        //pPlotter2.region(0).plot(hMeanCharge2D);
+
+        for (int ii=0;ii<NUM_CHANNELS;ii++){
+            int row = EcalMonitoringUtilities.getRowFromHistoID(ii);
+            int column = EcalMonitoringUtilities.getColumnFromHistoID(ii);	    
+            iTuple.add(aida.analysisFactory().createTupleFactory(aida.tree()).create("nTuple"+ii,"nTuple"+ii,"int fEvn=0 , double fCharge=0.,double fTime=0.",""));
+        }
+
+        for (int ii=0;ii<nDrivers;ii++){
+            hChargeVsEvn.add(aida.histogram2D("Driver"+ii,100,fEvnMinDraw,fEvnMaxDraw,100,fChargeMinDraw,fChargeMaxDraw));
+            pPlotter.region(ii).plot( hChargeVsEvn.get(ii));
+        }
+
+        pPlotter.show();
+        if (isMonitoringApp) pPlotter2.show();
+
+    }		
+
+    @Override
+    public void process(EventHeader event) {
+        runNumber = event.getRunNumber();
+        eventN++;
+        if (event.hasCollection(CalorimeterHit.class, inputCollection)) {
+            //List<BassRawCalorimeterHit> hits = event.get(BaseRawCalorimeterHit.class, inputCollectionRaw);
+            List<CalorimeterHit> hits = event.get(CalorimeterHit.class, inputCollection);
+            for (CalorimeterHit hit : hits) {
+
+                column = hit.getIdentifierFieldValue("ix");
+                row = hit.getIdentifierFieldValue("iy");
+                id = EcalMonitoringUtilities.getHistoIDFromRowColumn(row, column);
+                cellID=hit.getCellID();        
+                chid = ChannelCollection.findGeometric(cellID).getChannelId();
+
+                energy = hit.getCorrectedEnergy();
+                if (useRawEnergy){
+                    fillEnergy = getRawADCSum(energy,cellID);
+                }
+                else {
+                    fillEnergy = energy;
+                }
+                fillTime = hit.getTime();
+
+
+                //find the LED
+                if (row>0){
+                    ledid=LedTopMap.get(chid);
+                }
+                else if (row<0){
+                    ledid=LedBotMap.get(chid);
+                }
+                driverid=getDriver(ledid);
+                if (row<0) driverid+=4;
+
+
+
+                /*Skip the events under thr*/
+                if (energy<energyCut) continue;
+
+                /*First, check if this led is the one in the NEXT step. Therefore, increment by 1 the step*/
+                if (iStep[driverid]<(nSteps-1)){
+                    if (ledid==LEDStep[driverid][iStep[driverid]+1]){   
+                        iStep[driverid]++;
+                        System.out.println("LedAnalysis:: increment step ("+iStep[driverid]+") for driver "+driverid+" . Led ID: "+ledid+" Column: "+column+" Row: "+row);
+                        if (iStep[driverid]>0) drawProfiles(LEDStep[driverid][iStep[driverid]-1],driverid);      
+                    }	
+                }
+
+
+                if (iStep[driverid]==-1) continue;
+
+                /*Put this code here, since we want to always fill the ntuple*/
+                iTuple.get(id).fill(0,nEvents[id]);
+                iTuple.get(id).fill(1,fillEnergy);
+                iTuple.get(id).fill(2,fillTime);
+                iTuple.get(id).addRow();
+                nEvents[id]++;
+
+                /*Case 1: this led is the one in the corresponding step*/;
+                if (ledid==LEDStep[driverid][iStep[driverid]]){
+
+                }
+                else{	/*Case 2: this led is not one in the corresponding step (but maybe is the neighborhood??Ctalk??)*/;
+
+                }
+
+                /*Add a debug print */
+                if (eventN % 10000==0){
+                    System.out.println("Debug. LED ID: "+ledid+" DRIVER ID: "+driverid+" ECAL ID: "+id+" ROW: "+row+" COLUMN: "+column+ "HISTO ID: "+id);
+                }
+            }
+            if (eventN % 10000==0){
+                System.out.println("\n");
+            }
+        }		
+    }
+
+    /*
+     * The endOfData() method analises each ntuple to find the LED response.
+     * We cannot simply fit a gaussian to the energy distribution, since there is a high-energy tail due to the LED being turned on:
+     * When the LED turns on, it is "cold", and emits more light. Immediately, it starts to heat, and due to temperature effects the
+     * emitted light is less. This is clearly visible if one plots the charge VS the event number: the trend is decreasing, toward a
+     * plateau, that corresponds to the value at thermal equilibrium.
+     * 
+     * For (few) channels, the first charge values are close to 0, then charge grows rapidly, then it returns back to the plateau.
+     * To handle these, I always cut the first 10% events
+     * To properly handle this:
+     * 
+     * 1) First create a profile histogram, charge VS event number.
+     * 2) Fit it with something like "A*exp(-event_number/N0)+C. The function does not need to be extra-accurate at this stage
+     * 3) Cut the events with event_number < 5*N0.
+     * 4) Fit the remaining events with a gaussian.
+     */
+    @Override
+    public void endOfData() {
+        System.out.println("LedAnalysis::end of data");
+        System.out.println("LedAnalysis:: nEventsMin is: "+nEventsMin);
+
+        double e,eMin,eMax;
+        double t;
+        int n,nBins,nFits,nSkip;
+
+        int row, column;
+
+        String hName; 
+        IFunctionFactory fFactory=aida.analysisFactory().createFunctionFactory(aida.tree());
+
+        IFitResult fResult;
+        IFitter	   fFitter;
+
+        for (int id = 0; id < 11 * 47; id++) {
+
+            eMin=9999;
+            eMax=-9999;
+            row = EcalMonitoringUtilities.getRowFromHistoID(id);
+            column = EcalMonitoringUtilities.getColumnFromHistoID(id);
+            System.out.println("");
+            System.out.println("Doing channel: X= "+column+" Y= "+row);
+            System.out.println("Number of entries in analysis ntuple: "+iTuple.get(id).rows());
+            System.out.println("Number of recognized events: "+nEvents[id]);
+            /*Create the profile. Create it for all the channels, to keep sync.*/
+            nBins=nEvents[id]/100;
+            if (nBins<=0) nBins=1;
+
+            /*Clear previous*/
+
+            if (id>0){
+                aida.tree().rm("strip");
+                aida.tree().rm("fun0");
+                aida.tree().rm("fun1");
+            }
+            /*Create the profile.*/
+            cProfile=aida.profile1D("strip",nBins,-0.5,nEvents[id]*(1-skipInitial)+0.5);
+            cProfile.reset();
+            /*Create the function for the profile fit and the gaus fit*/
+            fFunction=fFactory.createFunctionFromScript("fun0",1,"A*exp(-x[0]/tau)+B","A,tau,B","",null);
+            fFunction1=fFactory.createFunctionByName("fun1","G");
+
+            if (EcalMonitoringUtilities.isInHole(row,column)==true){
+                System.out.println("Channel X= "+column+" Y= "+row+" is in hole. Skip");
+                hCharge.add(aida.histogram1D("charge_"+id,200,0.,1.)); //create here the histogram to keep sync
+                System.out.println("In hole, skip");
+                continue;
+            }
+            else if (nEvents[id]<nEventsMin) {
+                hCharge.add(aida.histogram1D("charge_"+id,200,0.,1.)); //create here the histogram to keep sync
+                System.err.println("LedAnalysis:: the channel X= "+column+" Y= "+row+" has not enough events "+nEvents[id]+" "+nEventsMin);
+
+                continue;
+            }			  
+
+            //Fill the profile*/
+            nSkip=(int)(nEvents[id]*skipInitial);
+            if (nSkip>iTuple.get(id).rows()){
+                System.out.println("Can't skip initial events?");
+                nSkip=0;
+            }
+            iTuple.get(id).start();
+            iTuple.get(id).skip(nSkip); //This is the work-around for those channels with charge starting from 0 and rapidly growing//
+            n=0;
+            iTuple.get(id).next(); 
+            while ( iTuple.get(id).next() ){
+                e=iTuple.get(id).getDouble(1);
+                if (e<eMin) eMin=e;           			  
+                if (e>eMax) eMax=e;
+                cProfile.fill(1.*n,e);
+                n++;
+            }			
+            fFitter=aida.analysisFactory().createFitFactory().createFitter("chi2","","v");
+
+            if (doFullAnalysis){ 
+                //Init function parameters
+                double[] initialPars={eMax-eMin,nEvents[id]/10.,eMin};
+                if (initialPars[0]<0) initialPars[0]=0;
+                fFunction.setParameters(initialPars);
+
+                //Do the fit      
+                System.out.println("LedAnalysis:: do profile fit "+id+" "+fFitter.engineName()+" "+fFitter.fitMethodName());
+                System.out.println("LedAnalysis:: initial parameters "+initialPars[0]+" "+initialPars[1]+" "+initialPars[2]);
+                fResult=fFitter.fit(cProfile,fFunction);
+                fPars     = fResult.fittedParameters();
+                fParErrs  = fResult.errors();
+                fParNames = fResult.fittedParameterNames();			
+                System.out.println("LedAnalysis:: Status= "+fResult.fitStatus()+" "+fResult.isValid()+" Chi2 = "+fResult.quality()+" NDF: "+fResult.ndf());
+                for(int i=0; i< fResult.fittedFunction().numberOfParameters(); i++ ){
+                    System.out.println(fParNames[i]+" : "+fPars[i]+" +- "+fParErrs[i]);
+                }  
+                fFunction.setParameters(fPars);
+
+
+                //Do again the fit: it is a terrible work-around
+                nFits=0;
+                if (Double.isNaN(fParErrs[1])){
+                    fPars=fPrevPars;
+                }
+                while (Double.isNaN(fParErrs[1])){
+                    System.out.println("LedAnalysis:: redo fit");
+                    fFunction.setParameters(fPars);
+                    fResult=fFitter.fit(cProfile,fFunction);
+                    fPars     = fResult.fittedParameters();
+                    fParErrs  = fResult.errors();
+                    System.out.println("LedAnalysis:: Status= "+fResult.fitStatus()+" "+fResult.isValid()+" Chi2 = "+fResult.quality()+" NDF: "+fResult.ndf());
+                    for(int i=0; i< fResult.fittedFunction().numberOfParameters(); i++ ){
+                        System.out.println(fParNames[i]+" : "+fPars[i]+" +- "+fParErrs[i]);
+                    }  
+                    fFunction.setParameters(fPars);
+                    nFits++;
+                    if (nFits>=10){
+                        System.out.println("LedAnalysis:: Error, too many fits without convergence");
+                        break;
+                    }
+                }
+                fPrevPars=Arrays.copyOf(fPars,fPars.length);
+                System.out.println("LedAnalysis:: fit "+id+" done");  
+
+                //Now we have the tau parameter. Take ONLY the events that are with N>5*tau/
+                //As a cross-check, also verify that tau > Nevents/10, otherwise skip the first Nevents/2
+                //and emit warning
+                nSkip=(int)( fPars[1]*5);
+                if (nSkip < (nEvents[id]*skipMin)){
+                    System.out.println("LedAnalysis:: Skip number too low: "+nSkip+" Increment it to "+nEvents[id]/2);
+                    nSkip=(int)(nEvents[id]*skipMin);
+                }
+                if (nSkip > nEvents[id]){
+                    System.out.println("LedAnalysis:: Skip number too high, reduce it");
+                    nSkip=(int)(nEvents[id]*skipMin);
+                }
+
+            }
+            else{
+                nSkip=(int)(nEvents[id]*(skipMin+skipInitial));
+            }
+
+            System.out.println("LedAnalysis:: gaus fit :: Going to skip "+nSkip+" out of "+nEvents[id]);
+            System.out.println("eMin is: "+eMin+" eMax is: "+eMax);
+            hCharge.add(aida.histogram1D("charge_"+id,200,eMin*0.9,eMax*1.1));
+
+
+            iTuple.get(id).start();
+            iTuple.get(id).skip(nSkip); 
+            n=0;
+            while (iTuple.get(id).next()){
+                e=iTuple.get(id).getDouble(1);
+                t=iTuple.get(id).getDouble(2);
+                hCharge.get(id).fill(e);
+                n++;
+            }			
+
+            /*Finally do the fit with the gaussian*/
+            double[] initialPars1={hCharge.get(id).maxBinHeight(),hCharge.get(id).mean(),hCharge.get(id).rms()};
+
+            System.out.println("LedAnalysis:: Gaus fit");
+            System.out.println("LedAnalysis:: initial parameters "+initialPars1[0]+" "+initialPars1[1]+" "+initialPars1[2]);
+
+            fFunction1.setParameters(initialPars1);
+            fResult=fFitter.fit(hCharge.get(id),fFunction1);
+            fPars     = fResult.fittedParameters();
+            fParErrs  = fResult.errors();
+            fParNames = fResult.fittedParameterNames();			
+            System.out.println("Status= "+fResult.fitStatus()+" "+fResult.isValid()+" Chi2 = "+fResult.quality()+" NDF: "+fResult.ndf());
+            for(int i=0; i< fResult.fittedFunction().numberOfParameters(); i++ ){
+                System.out.println(fParNames[i]+" : "+fPars[i]+" +- "+fParErrs[i]);
+            }  
+            fFunction1.setParameters(fPars);
+            mMean[id]=fPars[1];
+            mRMS[id]=fPars[2];
+
+            hMeanCharge2D.fill(column,row,mMean[id]);
+            System.out.println("\n");
+        }//End loop on channels
+
+
+
+        if ((pPlotter2!=null)&&(isMonitoringApp)){
+            style = pPlotter2.region(0).style();
+            style.setParameter("hist2DStyle", "colorMap");
+            style.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+            style.dataStyle().fillStyle().setParameter("showZeroHeightBins", Boolean.FALSE.toString()); 
+            pPlotter2.region(0).plot(hMeanCharge2D);
+            pPlotter2.region(0).refresh();
+        }
+        else{
+            IPlotterStyle pstyle =  aida.analysisFactory().createPlotterFactory().createPlotterStyle();
+            pPlotter2 = null;
+            pPlotter2 =  aida.analysisFactory().createPlotterFactory().create();
+            pstyle.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+            pstyle.dataStyle().fillStyle().setParameter("showZeroHeightBins", Boolean.FALSE.toString());
+            pstyle.setParameter("hist2DStyle", "colorMap");
+            if (pPlotter2!=null){
+                pPlotter2.createRegion().plot(hMeanCharge2D,pstyle);
+                pPlotter2.show();
+            }
+        }
+
+
+        askUploadToDBDialog();
+        synchronized (modalMonitor) {
+            try{
+                modalMonitor.wait(120000); //wait 2 minutes for user interaction.
+            }
+            catch(InterruptedException excp){
+                System.out.println("Got exception: "+excp);
+            }
+        }
+        if (m_ret==1){
+            System.out.println("OK, upload to DB");
+            try {
+                uploadToDB();
+            } catch (SQLException | DatabaseObjectException | ConditionsObjectException error) {
+                throw new RuntimeException("Error uploading to the database.", error);
+            }
+            if (isMonitoringApp){
+                System.out.println("Save an Elog too");
+                uploadToElog();
+            }
+        }
+
+        /*Write a file with the LED values*/
+        try {
+            if (useRawEnergy){
+                outFileName=runNumber+".raw.txt";
+            }
+            else{
+                outFileName=runNumber+".energy.txt";
+            }
+            PrintWriter writer = new PrintWriter(outFileName, "UTF-8");
+
+
+            for (int id = 0; id < 11 * 47; id++) {
+
+                row = EcalMonitoringUtilities.getRowFromHistoID(id);
+                column = EcalMonitoringUtilities.getColumnFromHistoID(id);
+                if (EcalMonitoringUtilities.isInHole(row, column)) continue;
+                if ((row == 0) || (column == 0)) continue;
+
+                writer.print(column+" "+row+" "+" "+ mMean[id]+" "+mRMS[id]+"\r\n");
+
+            }
+            writer.close();
+
+        } 
+        catch (FileNotFoundException fnfe) {
+
+            System.out.println(fnfe.getMessage());
+
+        }
+
+        catch (IOException ioe) {
+
+            System.out.println(ioe.getMessage());
+
+        }
+
+
+        System.out.println("EcalLedSequenceMonitor endOfData clear histograms"); 
+        for(int ii = 0; ii < NUM_CHANNELS; ii++) {   	
+            row=EcalMonitoringUtilities.getRowFromHistoID(ii);
+            column = EcalMonitoringUtilities.getColumnFromHistoID(ii);      	  
+            hName="charge_"+ii;	 
+            try{
+                aida.tree().rm(hName);
+            }
+            catch(IllegalArgumentException ee){
+                System.out.println("Got exception "+ee);
+            }
+
+            if (!saveTuple||(isMonitoringApp)){
+                hName="nTuple"+ii;
+                try{
+                    aida.tree().rm(hName);
+                }
+                catch(IllegalArgumentException ee){
+                    System.out.println("Got exception "+ee);
+                }
+            }
+
+        }
+        System.out.println("EcalLedSequenceMonitor endOfData clear histograms done");   
+        System.out.println("endOfData end");
+        System.out.println("The program is not stucked. It is writing the output AIDA file, this takes time!");
+    }/*End endOfData*/
+
+
+    /**
+     * This function returns the driver number (from 0 to 3) given the LED id.
+     * @param led
+     * @return
+     */
+    public int getDriver(int led){
+        int ret=-1;	
+        if ((led>=2)&&(led<56)) ret=0;
+        else if ((led>=56)&&(led<112)) ret=1;
+        else if ((led>=112)&&(led<168)) ret=2;
+        else if ((led>=168)&&(led<224)) ret=3;
+        return ret;
+    }
+
+    /**
+     * Very simple method to retreive the pedestal-subtracted raw Energy.
+     * If the gain changes (because we do a re-calibration), I do not want to include this in the LED analysis
+     * @param energy
+     * @param cellID
+     * @return
+     */
+    public double getRawADCSum(double energy,long cellID){
+        EcalChannelConstants channelData = ecalConditions.getChannelConstants(ecalConditions.getChannelCollection().findGeometric(cellID));
+        double RawSum=energy / EcalUtils.GeV;
+        double gain=channelData.getGain().getGain();
+        double ret=RawSum/gain;
+        //  System.out.println("A:C "+RawSum+" "+ret);
+        return ret;
+    }
+
+    private void uploadToDB() throws DatabaseObjectException, ConditionsObjectException, SQLException {
+        int x,y,id;
+        double mean,rms;
+        System.out.println(String.format("Uploading new led data to the database, runMin=%d, runMax=%d, tag=%s ....",
+                runNumber,runNumberMax,dbTag));
+
+        EcalLedCalibrationCollection led_calibrations =  new EcalLedCalibrationCollection();
+
+        TableMetaData tableMetaData = conditionsManager.findTableMetaData(dbTableName);
+        led_calibrations.setTableMetaData(tableMetaData);
+
+        for (int cid = 1; cid <= 442; cid++) {/*This is a loop over the channel ID, as in the conditions system*/
+            EcalChannel cc = findChannel(cid);
+            x = cc.getX(); //This is the column
+            y = cc.getY(); //This is the row
+            id=EcalMonitoringUtilities.getHistoIDFromRowColumn(y,x);
+            mean=mMean[id];
+            rms=mRMS[id];
+            led_calibrations.add(new EcalLedCalibration(cid,mean,rms));
+        }
+
+        int collectionId = -1;
+
+        try {
+            collectionId = conditionsManager.getCollectionId(led_calibrations, "loaded by EcalLedSequenceMonitor");
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+        System.err.println("CollectionID:  "+collectionId);
+        led_calibrations.insert();
+        ConditionsRecord conditionsRecord = new ConditionsRecord(
+                led_calibrations.getCollectionId(), runNumber, runNumberMax, dbTableName, dbTableName, 
+                "Generated by LedAnalysis from Run #"+runNumber, dbTag);
+        conditionsRecord.insert();
+
+        System.out.println("Upload to DB done");
+    }
+
+    private void uploadToElog(){
+        String path,exe,command,imgpath;
+        path="/home/hpsrun/LedSequenceData";
+        exe=path+"/doElog.csh";
+        imgpath=path+"/screenshots/"+runNumber+".png";
+
+        File f=new File(path);
+        if (!f.exists()){
+            System.err.println("LedMonitoringSequence:: wrong path");
+            return;
+        }
+        if (pPlotter2==null){
+            System.err.println("LedMonitoringSquence:: no plotter");
+            return;
+        }
+        try{
+            pPlotter2.writeToFile(imgpath);
+        }
+        catch(Exception e){
+            System.err.println("Exception "+e);
+        }
+        File f1=new File(exe);
+        if (!f1.exists()){
+            System.err.println("LedMonitoringSequence:: no script!");
+            return;
+        }   
+        command=exe+" "+imgpath;
+        try{
+            System.out.println("LedMonitoringSequence:: try this command: "+command);
+            Runtime.getRuntime().exec(command);
+        }
+        catch(Exception e){
+            System.err.println("Exception "+e);
+        }
+    }
+
+
+    private void drawProfiles(int ledID,int driverID){
+
+        int m_column,m_row,m_ledID,m_chID,m_ID,m_driverID;
+
+        m_ledID = ledID;
+        m_driverID = driverID;
+        m_chID = 0;
+
+
+        if (m_driverID<=3) m_chID = LedTopMapInverted.get(ledID);
+        else m_chID = LedBotMapInverted.get(ledID);
+
+        m_column=findChannel(m_chID).getX();
+        m_row=findChannel(m_chID).getY();
+        m_ID=EcalMonitoringUtilities.getHistoIDFromRowColumn(m_row, m_column);
+        /* 
         System.out.println("Going to draw LED id "+m_ledID+" X= "+m_column+" Y= "+m_row+" driver: "+m_driverID);
         System.out.println("Ch_ID: "+m_chID);
         System.out.println("Histo ID:"+m_ID);
         System.out.println("Events: "+iTuple.get(m_ID).rows());
-		 */      
-		hChargeVsEvn.get(m_driverID).reset();
-		hChargeVsEvn.get(m_driverID).setTitle("Driver_"+m_driverID+" Led_"+ledID);
-		IEvaluator evaluatorX = aida.analysisFactory().createTupleFactory(aida.analysisFactory().createTreeFactory().create()).createEvaluator("fEvn");
-		IEvaluator evaluatorY = aida.analysisFactory().createTupleFactory(aida.analysisFactory().createTreeFactory().create()).createEvaluator("fCharge");  
-
-		iTuple.get(m_ID).project(hChargeVsEvn.get(m_driverID),evaluatorX,evaluatorY);
-
-		pPlotter.region(m_driverID).clear();  
-		pPlotter.region(m_driverID).plot(hChargeVsEvn.get(m_driverID));
-		pPlotter.region(m_driverID).refresh();
-
-	}
-
-	private EcalChannel findChannel(int channel_id) {
-		return ecalConditions.getChannelCollection().findChannel(channel_id);
-	}
-
-
-	private void askUploadToDBDialog(){
-		m_ret=0;
-
-		okButton = new JButton("OK");
-		cancelButton = new JButton("Cancel");
-		labelString = "<html> Update conditions to DB <br> for run: <br> "+runNumber+" - "+runNumberMax+" <br> ???? <br> "
-				+ "Use the monitoring app to look at the map<br>" 
-				+ "(Tab LED sequence)<br"
-				+"Reply in 60 seconds<br>"+"</html>";   
-		label = new JLabel( labelString);
-
-		frame  = new JFrame("Upload to DB?");
-		frame.setSize(500,250);
-		panel = new JPanel();
-		frame.add(panel);
-
-
-		// dialog = new JDialog((JFrame)null, "User selection");
-		// dialog.setSize(200,200);
-		// dialog.setLayout(new FlowLayout());
-		// dialog.add(label);
-		// dialog.add(cancelButton);
-		// dialog.add(okButton);
-		// dialog.setVisible(true);
-		//dialog.pack();
-		panel.add(label);
-		panel.add(cancelButton);
-		panel.add(okButton);
-
-		frame.setVisible(true);
-		okButton.addActionListener(new ActionListener(){
-			public void actionPerformed(ActionEvent event)
-			{
-				m_ret=1;
-				frame.dispose();    
-				synchronized(modalMonitor)
-				{
-					System.out.println("Ok pressed");
-					modalMonitor.notify();
-				}
-			}
-		}
-				);
-
-		cancelButton.addActionListener(new ActionListener(){
-			public void actionPerformed(ActionEvent event)
-			{
-				m_ret=0;
-				frame.dispose();   
-				synchronized(modalMonitor)
-				{
-					System.out.println("Cancel pressed");
-					modalMonitor.notify();
-				}
-			}
-		}
-				);
-
-		System.out.println("askUploadDB done");
-	}
+         */      
+        hChargeVsEvn.get(m_driverID).reset();
+        hChargeVsEvn.get(m_driverID).setTitle("Driver_"+m_driverID+" Led_"+ledID);
+        IEvaluator evaluatorX = aida.analysisFactory().createTupleFactory(aida.analysisFactory().createTreeFactory().create()).createEvaluator("fEvn");
+        IEvaluator evaluatorY = aida.analysisFactory().createTupleFactory(aida.analysisFactory().createTreeFactory().create()).createEvaluator("fCharge");  
+
+        iTuple.get(m_ID).project(hChargeVsEvn.get(m_driverID),evaluatorX,evaluatorY);
+
+        pPlotter.region(m_driverID).clear();  
+        pPlotter.region(m_driverID).plot(hChargeVsEvn.get(m_driverID));
+        pPlotter.region(m_driverID).refresh();
+
+    }
+
+    private EcalChannel findChannel(int channel_id) {
+        return ecalConditions.getChannelCollection().findChannel(channel_id);
+    }
+
+
+    private void askUploadToDBDialog(){
+        m_ret=0;
+
+        okButton = new JButton("OK");
+        cancelButton = new JButton("Cancel");
+        labelString = "<html> Update conditions to DB <br> for run: <br> "+runNumber+" - "+runNumberMax+" <br> ???? <br> "
+                + "Use the monitoring app to look at the map<br>" 
+                + "(Tab LED sequence)<br"
+                +"Reply in 60 seconds<br>"+"</html>";   
+        label = new JLabel( labelString);
+
+        frame  = new JFrame("Upload to DB?");
+        frame.setSize(500,250);
+        panel = new JPanel();
+        frame.add(panel);
+
+
+        // dialog = new JDialog((JFrame)null, "User selection");
+        // dialog.setSize(200,200);
+        // dialog.setLayout(new FlowLayout());
+        // dialog.add(label);
+        // dialog.add(cancelButton);
+        // dialog.add(okButton);
+        // dialog.setVisible(true);
+        //dialog.pack();
+        panel.add(label);
+        panel.add(cancelButton);
+        panel.add(okButton);
+
+        frame.setVisible(true);
+        okButton.addActionListener(new ActionListener(){
+            public void actionPerformed(ActionEvent event)
+            {
+                m_ret=1;
+                frame.dispose();    
+                synchronized(modalMonitor)
+                {
+                    System.out.println("Ok pressed");
+                    modalMonitor.notify();
+                }
+            }
+        }
+                );
+
+        cancelButton.addActionListener(new ActionListener(){
+            public void actionPerformed(ActionEvent event)
+            {
+                m_ret=0;
+                frame.dispose();   
+                synchronized(modalMonitor)
+                {
+                    System.out.println("Cancel pressed");
+                    modalMonitor.notify();
+                }
+            }
+        }
+                );
+
+        System.out.println("askUploadDB done");
+    }
 
 }

Modified: java/trunk/monitoring-drivers/src/main/java/org/hps/monitoring/ecal/plots/EcalMonitoringUtilities.java
 =============================================================================
--- java/trunk/monitoring-drivers/src/main/java/org/hps/monitoring/ecal/plots/EcalMonitoringUtilities.java	(original)
+++ java/trunk/monitoring-drivers/src/main/java/org/hps/monitoring/ecal/plots/EcalMonitoringUtilities.java	Tue Oct 27 11:33:16 2015
@@ -111,7 +111,7 @@
 
     public static Boolean isInHole(final int row, final int column) {
         if (row == 1 || row == -1) {
-            if ((column <= XHOLESTART + XHOLEWIDTH) && (column >= XHOLESTART)) {
+            if ((column < XHOLESTART + XHOLEWIDTH) && (column >= XHOLESTART)) {
                 return true;
             }
         }