Author: [log in to unmask] Date: Fri Mar 6 22:41:24 2015 New Revision: 2328 Log: Add a basic raw data monitoring station and some ECAL monitoring utils. Added: java/trunk/monitoring-drivers/src/main/java/org/hps/monitoring/drivers/ecal/ java/trunk/monitoring-drivers/src/main/java/org/hps/monitoring/drivers/ecal/EcalMonitoringUtilities.java java/trunk/monitoring-drivers/src/main/java/org/hps/monitoring/drivers/ecal/RawCalorimeterHitMonitoringDriver.java java/trunk/steering-files/src/main/resources/org/hps/steering/monitoring/ecal/ java/trunk/steering-files/src/main/resources/org/hps/steering/monitoring/ecal/RawDataMonitoring.lcsim Added: java/trunk/monitoring-drivers/src/main/java/org/hps/monitoring/drivers/ecal/EcalMonitoringUtilities.java ============================================================================= --- java/trunk/monitoring-drivers/src/main/java/org/hps/monitoring/drivers/ecal/EcalMonitoringUtilities.java (added) +++ java/trunk/monitoring-drivers/src/main/java/org/hps/monitoring/drivers/ecal/EcalMonitoringUtilities.java Fri Mar 6 22:41:24 2015 @@ -0,0 +1,82 @@ +package org.hps.monitoring.drivers.ecal; + +import hep.aida.IBaseHistogram; +import hep.aida.ICloud1D; +import hep.aida.IHistogram1D; +import hep.aida.IHistogram2D; +import hep.aida.IPlotter; +import hep.aida.IPlotterFactory; +import hep.aida.IPlotterStyle; +import hep.aida.IProfile1D; +import hep.aida.IProfile2D; +import hep.aida.ref.plotter.style.registry.IStyleStore; +import hep.aida.ref.plotter.style.registry.StyleRegistry; + +import org.lcsim.util.aida.AIDA; + +class EcalMonitoringUtilities { + + // FIXME: Copied from EcalRawConverterDriver. + static int INTEGRAL_WINDOW = 30; + + static double X_BIN_EDGE_2D = 23.25; + static double Y_BIN_EDGE_2D = 5.25; + static int N_BINS_X_2D = 47; + static int N_BINS_Y_2D = 11; + + static int N_CHANNELS_1D = 442; + + static double CHANNELS_LOWER_EDGE_1D = 0.5; + static double CHANNELS_UPPTER_EDGE_1D = 441.5; + + static final String EXTRA_DATA_RELATIONS_NAME = "EcalReadoutExtraDataRelations"; + + // TODO: add more range constants for common quantities like hit energy, timestamp, ADC values, cluster position, etc. + + static AIDA aida = AIDA.defaultInstance(); + + static IHistogram2D createChannelHistogram2D(String name) { + return aida.histogram2D(name, N_BINS_X_2D, -X_BIN_EDGE_2D, X_BIN_EDGE_2D, N_BINS_Y_2D, -Y_BIN_EDGE_2D, Y_BIN_EDGE_2D); + } + + static IProfile2D createChannelProfile2D(String name) { + return aida.profile2D(name, N_BINS_X_2D, -X_BIN_EDGE_2D, X_BIN_EDGE_2D, N_BINS_Y_2D, -Y_BIN_EDGE_2D, Y_BIN_EDGE_2D); + } + + static IHistogram1D createChannelHistogram1D(String name) { + return aida.histogram1D(name, N_CHANNELS_1D, CHANNELS_LOWER_EDGE_1D, CHANNELS_UPPTER_EDGE_1D); + } + + static IProfile1D createChannelProfile1D(String name) { + return aida.profile1D(name, N_CHANNELS_1D, CHANNELS_LOWER_EDGE_1D, CHANNELS_UPPTER_EDGE_1D); + } + + static IPlotter plot(IPlotterFactory plotterFactory, IBaseHistogram histogram, IPlotterStyle style, boolean show) { + if (style == null) { + style = getPlotterStyle(histogram); + } + IPlotter plotter = plotterFactory.create(histogram.title()); + plotter.createRegion(); + plotter.region(0).plot(histogram, style); + if (show) { + plotter.show(); + } + return plotter; + } + + static IPlotterStyle getPlotterStyle(IBaseHistogram histogram) { + StyleRegistry styleRegistry = StyleRegistry.getStyleRegistry(); + IStyleStore store = styleRegistry.getStore("DefaultStyleStore"); + IPlotterStyle style = null; + if ((histogram instanceof IHistogram1D) || (histogram instanceof ICloud1D) || (histogram instanceof IProfile1D)) { + style = store.getStyle("DefaultHistogram1DStyle"); + } else if ((histogram instanceof IHistogram2D) || (histogram instanceof IProfile2D)) { + style = store.getStyle("DefaultColorMapStyle"); + } + if (style == null) { + throw new RuntimeException("A default style could not be found for " + histogram.title()); + } + return style; + } + +} Added: java/trunk/monitoring-drivers/src/main/java/org/hps/monitoring/drivers/ecal/RawCalorimeterHitMonitoringDriver.java ============================================================================= --- java/trunk/monitoring-drivers/src/main/java/org/hps/monitoring/drivers/ecal/RawCalorimeterHitMonitoringDriver.java (added) +++ java/trunk/monitoring-drivers/src/main/java/org/hps/monitoring/drivers/ecal/RawCalorimeterHitMonitoringDriver.java Fri Mar 6 22:41:24 2015 @@ -0,0 +1,200 @@ +package org.hps.monitoring.drivers.ecal; + +import static org.hps.monitoring.drivers.ecal.EcalMonitoringUtilities.EXTRA_DATA_RELATIONS_NAME; +import static org.hps.monitoring.drivers.ecal.EcalMonitoringUtilities.INTEGRAL_WINDOW; +import static org.hps.monitoring.drivers.ecal.EcalMonitoringUtilities.createChannelHistogram2D; +import static org.hps.monitoring.drivers.ecal.EcalMonitoringUtilities.createChannelProfile2D; +import static org.hps.monitoring.drivers.ecal.EcalMonitoringUtilities.plot; +import hep.aida.ICloud1D; +import hep.aida.IHistogram1D; +import hep.aida.IHistogram2D; +import hep.aida.IPlotterFactory; +import hep.aida.IProfile2D; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import org.hps.conditions.database.DatabaseConditionsManager; +import org.hps.conditions.ecal.EcalChannel; +import org.hps.conditions.ecal.EcalChannelConstants; +import org.hps.conditions.ecal.EcalConditions; +import org.hps.recon.ecal.HitExtraData; +import org.lcsim.detector.identifier.IIdentifier; +import org.lcsim.detector.identifier.IIdentifierHelper; +import org.lcsim.detector.identifier.Identifier; +import org.lcsim.event.EventHeader; +import org.lcsim.event.GenericObject; +import org.lcsim.event.LCRelation; +import org.lcsim.event.RawCalorimeterHit; +import org.lcsim.geometry.Detector; +import org.lcsim.geometry.Subdetector; +import org.lcsim.util.Driver; +import org.lcsim.util.aida.AIDA; + +/** + * This is a set of detailed plots for monitoring ECAL raw data collections in integral mode (modes 3 and 7). + * + * @author Jeremy McCormick <[log in to unmask]> + */ +public class RawCalorimeterHitMonitoringDriver extends Driver { + + ICloud1D pedSubAmplitudeC1D; + IHistogram1D amplitudeH1D; + ICloud1D timestampC1D; + ICloud1D amplitudeLowC1D; + ICloud1D amplitudeHighC1D; + IHistogram1D hitsPerEventH1D; + IHistogram2D hitMapH2D; + IHistogram2D occupancyH2D; + IProfile2D amplitudeHighP2D; + IProfile2D amplitudeLowP2D; + IProfile2D timestampP2D; + + Map<Long, Integer> occupancyMap = new HashMap<Long, Integer>(); + int accumulatedEvents = 0; + long lastUpdatedMillis = 0; + long occupancyUpdateMillis = 5000; // Refresh occupancy plots every 5 seconds. + + AIDA aida = AIDA.defaultInstance(); + + EcalConditions conditions; + + String rawCalorimeterHitCollectionName = "EcalReadoutHits"; + Subdetector subdetector; + IIdentifierHelper helper; + + public void setOccupancyUpdateMillis(long occupancyUpdateMillis) { + this.occupancyUpdateMillis = occupancyUpdateMillis; + } + + public void setRawCalorimeterHitCollectionName(String rawCalorimeterHitCollectionName) { + this.rawCalorimeterHitCollectionName = rawCalorimeterHitCollectionName; + } + + public void detectorChanged(Detector detector) { + DatabaseConditionsManager manager = DatabaseConditionsManager.getInstance(); + conditions = manager.getCachedConditions(EcalConditions.class, "ecal_conditions").getCachedData(); + subdetector = detector.getSubdetector("Ecal"); + helper = subdetector.getDetectorElement().getIdentifierHelper(); + } + + public void startOfData() { + pedSubAmplitudeC1D = aida.cloud1D("Pedestal Sub Amplitude"); + amplitudeH1D = aida.histogram1D("Amplitude", 150, 0.5, 14999.5); + timestampC1D = aida.cloud1D("Timestamp"); + amplitudeLowC1D = aida.cloud1D("Mode 7 Amplitude Low"); + amplitudeHighC1D = aida.cloud1D("Mode 7 Amplitude High"); + hitsPerEventH1D = aida.histogram1D("Hits Per Event", 100, -0.5, 99.5); + hitMapH2D = createChannelHistogram2D("Hit Map"); + occupancyH2D = createChannelHistogram2D("Hit Occupancy"); + amplitudeHighP2D = createChannelProfile2D("Mode 7 Average Amplitude High"); + amplitudeLowP2D = createChannelProfile2D("Mode 7 Average Amplitude Low"); + timestampP2D = createChannelProfile2D("Average Timestamp"); + + IPlotterFactory plotterFactory = aida.analysisFactory().createPlotterFactory("ECAL - " + rawCalorimeterHitCollectionName); + + plot(plotterFactory, pedSubAmplitudeC1D, null, true); + plot(plotterFactory, amplitudeH1D, null, true); + plot(plotterFactory, timestampC1D, null, true); + plot(plotterFactory, amplitudeLowC1D, null, true); + plot(plotterFactory, amplitudeHighC1D, null, true); + plot(plotterFactory, hitsPerEventH1D, null, true); + plot(plotterFactory, hitMapH2D, null, true); + plot(plotterFactory, occupancyH2D, null, true); + plot(plotterFactory, amplitudeHighP2D, null, true); + plot(plotterFactory, amplitudeLowP2D, null, true); + plot(plotterFactory, timestampP2D, null, true); + + lastUpdatedMillis = System.currentTimeMillis(); + } + + public void process(EventHeader event) { + + if (event.hasCollection(RawCalorimeterHit.class, rawCalorimeterHitCollectionName)) { + + List<RawCalorimeterHit> rawHits = event.get(RawCalorimeterHit.class, rawCalorimeterHitCollectionName); + + /* + * Do basic plots of RawCalorimeterHit data. + */ + hitsPerEventH1D.fill(rawHits.size()); + Set<RawCalorimeterHit> uniqueRawHits = new HashSet<RawCalorimeterHit>(); + for (RawCalorimeterHit rawHit : rawHits) { + amplitudeH1D.fill(rawHit.getAmplitude()); + timestampC1D.fill(rawHit.getTimeStamp()); + EcalChannel channel = conditions.getChannelCollection().findGeometric(rawHit.getCellID()); + EcalChannelConstants constants = conditions.getChannelConstants(channel); + pedSubAmplitudeC1D.fill(rawHit.getAmplitude() - (constants.getCalibration().getPedestal() * INTEGRAL_WINDOW)); + + int ix = helper.getValue(new Identifier(rawHit.getCellID()), "ix"); + int iy = helper.getValue(new Identifier(rawHit.getCellID()), "iy"); + hitMapH2D.fill(ix, iy); + + timestampP2D.fill(ix, iy, rawHit.getTimeStamp()); + + uniqueRawHits.add(rawHit); + } + + /* + * Update and plot occupancies based on unique hits in the event. + */ + for (RawCalorimeterHit rawHit : uniqueRawHits) { + + // Add entry if does not exist. + if (occupancyMap.get(rawHit.getCellID()) == null) { + occupancyMap.put(rawHit.getCellID(), 0); + } + + // Increment hit count by one for this hit. + int nHits = occupancyMap.get(rawHit.getCellID()) + 1; + occupancyMap.put(rawHit.getCellID(), nHits); + } + ++accumulatedEvents; + long elapsed = System.currentTimeMillis() - lastUpdatedMillis; + if (elapsed >= occupancyUpdateMillis) { + occupancyH2D.reset(); + for (Entry<Long, Integer> entry : occupancyMap.entrySet()) { + IIdentifier hitId = new Identifier(entry.getKey()); + int ix = helper.getValue(hitId, "ix"); + int iy = helper.getValue(hitId, "iy"); + occupancyH2D.fill(ix, iy, (double) entry.getValue() / (double) accumulatedEvents); + } + lastUpdatedMillis = System.currentTimeMillis(); + accumulatedEvents = 0; + occupancyMap.clear(); + } + + /* + * Plot from mode 7 data if it exists. + */ + if (event.hasCollection(LCRelation.class, EXTRA_DATA_RELATIONS_NAME)) { + List<LCRelation> extraDataRelations = event.get(LCRelation.class, EXTRA_DATA_RELATIONS_NAME); + if (extraDataRelations != null) { + for (LCRelation rel : event.get(LCRelation.class, EXTRA_DATA_RELATIONS_NAME)) { + GenericObject extraData = (GenericObject) rel.getTo(); + if (extraData instanceof HitExtraData.Mode7Data) { + HitExtraData.Mode7Data mode7Data = (HitExtraData.Mode7Data) extraData; + amplitudeHighC1D.fill(mode7Data.getAmplHigh()); + amplitudeLowC1D.fill(mode7Data.getAmplLow()); + + RawCalorimeterHit rawHit = (RawCalorimeterHit) rel.getFrom(); + // FIXME: Duplicated from RawTrackerHit loop from above. + int ix = helper.getValue(new Identifier(rawHit.getCellID()), "ix"); + int iy = helper.getValue(new Identifier(rawHit.getCellID()), "iy"); + + // Average amplitude high. + amplitudeHighP2D.fill(ix, iy, mode7Data.getAmplHigh()); + + // Average amplitude low. + amplitudeLowP2D.fill(ix, iy, mode7Data.getAmplLow()); + } + } + } + } + } + } +} Added: java/trunk/steering-files/src/main/resources/org/hps/steering/monitoring/ecal/RawDataMonitoring.lcsim ============================================================================= --- java/trunk/steering-files/src/main/resources/org/hps/steering/monitoring/ecal/RawDataMonitoring.lcsim (added) +++ java/trunk/steering-files/src/main/resources/org/hps/steering/monitoring/ecal/RawDataMonitoring.lcsim Fri Mar 6 22:41:24 2015 @@ -0,0 +1,17 @@ +<!-- + Steering configuration for data monitoring of RawCalorimeterHit collections. +--> +<lcsim xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:noNamespaceSchemaLocation="http://www.lcsim.org/schemas/lcsim/1.0/lcsim.xsd"> + <execute> + <driver name="EventMarkerDriver"/> + <driver name="RawCalorimeterHitMonitoringDriver"/> + <!-- <driver name="RawCalorimeterHitStripChartDriver"/> --> + </execute> + <drivers> + <driver name="EventMarkerDriver" type="org.lcsim.job.EventMarkerDriver"> + <eventInterval>1</eventInterval> + </driver> + <driver name="RawCalorimeterHitMonitoringDriver" type="org.hps.monitoring.drivers.ecal.RawCalorimeterHitMonitoringDriver"> + </driver> + </drivers> +</lcsim>