Author: [log in to unmask] Date: Tue Jan 27 10:34:17 2015 New Revision: 1994 Log: Improvements to monitoring run panel. HPSJAVA-402 Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/MonitoringApplication.java java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/RunPanel.java java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/model/ConfigurationModel.java java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/model/RunModel.java Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/MonitoringApplication.java ============================================================================= --- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/MonitoringApplication.java (original) +++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/MonitoringApplication.java Tue Jan 27 10:34:17 2015 @@ -1,30 +1,8 @@ package org.hps.monitoring.gui; -import static org.hps.monitoring.gui.Commands.AIDA_AUTO_SAVE; -import static org.hps.monitoring.gui.Commands.CHOOSE_LOG_FILE; -import static org.hps.monitoring.gui.Commands.CLEAR_LOG_TABLE; -import static org.hps.monitoring.gui.Commands.CONNECT; -import static org.hps.monitoring.gui.Commands.DISCONNECT; -import static org.hps.monitoring.gui.Commands.EXIT; -import static org.hps.monitoring.gui.Commands.LOAD_DEFAULT_CONFIG_FILE; -import static org.hps.monitoring.gui.Commands.LOG_LEVEL_CHANGED; -import static org.hps.monitoring.gui.Commands.LOG_TO_TERMINAL; -import static org.hps.monitoring.gui.Commands.NEXT; -import static org.hps.monitoring.gui.Commands.PAUSE; -import static org.hps.monitoring.gui.Commands.RESET_PLOTS; -import static org.hps.monitoring.gui.Commands.RESTORE_DEFAULT_GUI_LAYOUT; -import static org.hps.monitoring.gui.Commands.RESUME; -import static org.hps.monitoring.gui.Commands.SAVE_CONFIG_FILE; -import static org.hps.monitoring.gui.Commands.SAVE_LAYOUT; -import static org.hps.monitoring.gui.Commands.SAVE_LOG_TABLE; -import static org.hps.monitoring.gui.Commands.SAVE_PLOTS; -import static org.hps.monitoring.gui.Commands.SCREENSHOT; -import static org.hps.monitoring.gui.Commands.SELECT_CONFIG_FILE; -import static org.hps.monitoring.gui.Commands.SHOW_SETTINGS; -import static org.hps.monitoring.gui.Commands.VALIDATE_DATA_FILE; +import static org.hps.monitoring.gui.Commands.*; import static org.hps.monitoring.gui.model.ConfigurationModel.MONITORING_APPLICATION_LAYOUT_PROPERTY; import static org.hps.monitoring.gui.model.ConfigurationModel.SAVE_LAYOUT_PROPERTY; -import hep.aida.ITree; import hep.aida.jfree.AnalysisFactory; import hep.aida.jfree.plotter.PlotterRegion; import hep.aida.jfree.plotter.PlotterRegionListener; @@ -1368,10 +1346,7 @@ // RunPanel updater. loopConfig.add(runPanel.new RunModelUpdater()); - - // Data rate updater for RunPanel. - loopConfig.add(runPanel.new DataRateUpdater()); - + // Setup for conditions activation via EVIO events. loopConfig.add(new EvioDetectorConditionsProcessor(configurationModel.getDetectorName())); Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/RunPanel.java ============================================================================= --- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/RunPanel.java (original) +++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/RunPanel.java Tue Jan 27 10:34:17 2015 @@ -6,6 +6,8 @@ import java.awt.FlowLayout; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import java.text.DecimalFormat; +import java.text.NumberFormat; import java.util.Date; import java.util.Timer; import java.util.TimerTask; @@ -19,17 +21,15 @@ import org.hps.record.composite.CompositeRecord; import org.hps.record.composite.CompositeRecordProcessor; import org.hps.record.evio.EvioEventUtilities; +import org.jlab.coda.jevio.BaseStructure; import org.jlab.coda.jevio.EvioEvent; +import org.lcsim.event.EventHeader; /** * Dashboard for displaying information about the current run. * @author Jeremy McCormick <[log in to unmask]> */ -// TODO: Add current data rate field (measured over last ~second). -// TOOD: Add current event rate field (measured over last ~second). // TODO: Add event sequence number from CompositeRecord. -// TODO: Add average data rate field (over entire session). -// TODO: Add average proc time per event field (over entire session). class RunPanel extends JPanel implements PropertyChangeListener { FieldPanel runNumberField = new FieldPanel("Run Number", "", 10, false); @@ -39,14 +39,14 @@ FieldPanel totalEventsField = new FieldPanel("Total Events in Run", "", 14, false); FieldPanel elapsedTimeField = new FieldPanel("Elapsed Time [sec]", "", 14, false); FieldPanel eventsReceivedField = new FieldPanel("Events Received", "", 14, false); - FieldPanel dataReceivedField = new FieldPanel("Data Received [bytes]", "", 14, false); + FieldPanel dataReceivedField = new FieldPanel("Data Received [MB]", "", 14, false); FieldPanel eventNumberField = new FieldPanel("Event Number", "", 14, false); - FieldPanel dataRateField = new FieldPanel("Data Rate [mb/s]", "", 12, false); - - Timer timer; - long jobStartMillis; + FieldPanel dataRateField = new FieldPanel("Data Rate [MB/s]", "", 12, false); + FieldPanel eventRateField = new FieldPanel("Event Rate [evt/s]", "", 14, false); RunModel model; + + NumberFormat formatter = new DecimalFormat("#0.00"); RunPanel(RunModel model) { this.model = model; @@ -67,52 +67,91 @@ add(dataReceivedField); add(eventNumberField); add(dataRateField); + add(eventRateField); this.setMinimumSize(new Dimension(0, 240)); } - void startJobTimer() { - timer = new Timer("JobTimer"); - jobStartMillis = System.currentTimeMillis(); - TimerTask updateTimeTask = new TimerTask() { - public void run() { - final int elapsedTime = (int) ((System.currentTimeMillis() - jobStartMillis) / 1000); - model.setElapsedTime(elapsedTime); - } - }; - timer.scheduleAtFixedRate(updateTimeTask, 0, 1000); - } - - void stopRunTimer() { - timer.cancel(); - } - class RunModelUpdater extends CompositeRecordProcessor { + Timer timer; + + int eventsReceived; + double bytesReceived; + int totalEvents; + int eventNumber; + int runNumber = -1; + long jobStartMillis; + @Override public void startJob() { model.reset(); - RunPanel.this.startJobTimer(); + jobStartMillis = System.currentTimeMillis(); + + // Start the timer to update GUI components about once per second. + timer = new Timer("RunModelUpdaterTimer"); + TimerTask task = new TimerTask() { + public void run() { + final int elapsedTime = (int) ((System.currentTimeMillis() - jobStartMillis) / 1000); + double megaBytesReceived = bytesReceived / 1000000; + totalEvents += eventsReceived; + + model.setElapsedTime(elapsedTime); + model.setEventsReceived(totalEvents); + model.setDataRate(megaBytesReceived); + model.addDataReceived(megaBytesReceived); + model.setEventNumber(eventNumber); + model.setEventRate(eventsReceived); + eventsReceived = 0; + bytesReceived = 0; + eventNumber = 0; + } + }; + timer.scheduleAtFixedRate(task, 0, 1000); } @Override public void process(CompositeRecord event) { - // FIXME: This should not update every event. It overloads the EDT. - // Listeners can be enabled/disabled based on an event interval. - model.incrementEventsReceived(); - EvioEvent evioEvent = event.getEvioEvent(); - if (event.getEtEvent() != null && event.getEvioEvent() == null) { - model.addDataReceived(event.getEtEvent().getData().length); - } else if (evioEvent != null) { - model.addDataReceived((long) evioEvent.getTotalBytes()); - model.setEventNumber(evioEvent.getEventNumber()); + ++eventsReceived; + if (event.getEvioEvent() != null) { + EvioEvent evioEvent = event.getEvioEvent(); + bytesReceived += evioEvent.getTotalBytes(); + eventNumber = evioEvent.getEventNumber(); if (EvioEventUtilities.isPreStartEvent(evioEvent)) { + // Get run start info from pre start event. startRun(evioEvent); } else if (EvioEventUtilities.isEndEvent(evioEvent)) { + // Get end run info from end event. endRun(evioEvent); - } + } else { + // Check for run info in head bank. + checkHeadBank(evioEvent); + } + } else if (event.getEtEvent() != null) { + bytesReceived += event.getEtEvent().getData().length; + eventNumber = event.getEtEvent().getId(); } else if (event.getLcioEvent() != null) { - model.setEventNumber(event.getLcioEvent().getEventNumber()); + EventHeader lcioEvent = event.getLcioEvent(); + eventNumber = lcioEvent.getEventNumber(); + if (lcioEvent.getRunNumber() != runNumber) { + runNumber = lcioEvent.getRunNumber(); + startRun(lcioEvent); + } + } + } + + /** + * @param evioEvent + */ + private void checkHeadBank(EvioEvent evioEvent) { + BaseStructure headBank = EvioEventUtilities.getHeadBank(evioEvent); + if (headBank != null) { + int headBankRun = headBank.getIntData()[1]; + if (headBankRun != runNumber) { + runNumber = headBankRun; + model.setRunNumber(headBankRun); + model.setStartDate(new Date(headBank.getIntData()[3])); + } } } @@ -136,7 +175,7 @@ int[] data = EvioEventUtilities.getControlEventData(evioEvent); if (data != null) { int seconds = data[0]; - int runNumber = data[1]; + runNumber = data[1]; long startMillis = ((long) seconds) * 1000; // Update the GUI. @@ -144,58 +183,20 @@ model.setStartDate(new Date(startMillis)); } } - + + private void startRun(EventHeader lcioEvent) { + model.setRunNumber(lcioEvent.getRunNumber()); + model.setStartDate(new Date(lcioEvent.getTimeStamp() / 1000)); + } + @Override public void endJob() { - RunPanel.this.stopRunTimer(); + timer.cancel(); } } /** - * Update the data rate field at about once per second based on how - * many bytes were received by the processor in that interval. - * The actual number of milliseconds between updates is not computed, - * so this might be slightly inaccurate. - */ - class DataRateUpdater extends CompositeRecordProcessor { - - double bytesReceived = 0; - Timer dataRateTimer; - - @Override - public void startJob() { - // Start the timer to execute data rate calculation about once per second. - dataRateTimer = new Timer("DataRateTimer"); - TimerTask dataRateTask = new TimerTask() { - public void run() { - double megaBytesReceived = bytesReceived / 1000000; - model.setDataRate(megaBytesReceived); - bytesReceived = 0; - } - }; - dataRateTimer.scheduleAtFixedRate(dataRateTask, 0, 1000); - } - - @Override - public void process(CompositeRecord event) { - if (event.getEtEvent() != null && event.getEvioEvent() == null) { - // Use ET events for length. - bytesReceived += event.getEtEvent().getData().length; - } else if (event.getEvioEvent() != null) { - // Use EVIO events for length. - bytesReceived += event.getEvioEvent().getTotalBytes(); - } - // FIXME: If there is an LCIO source only, it is not easy to get the data length in bytes! - } - - public void endJob() { - // Kill the timer. - dataRateTimer.cancel(); - } - } - - /** - * Update the GUI from changes in the underlying RunModel object. + * Update the GUI from changes to the backing RunModel object. */ @Override public void propertyChange(PropertyChangeEvent evt) { @@ -221,11 +222,13 @@ } else if (ELAPSED_TIME_PROPERTY.equals(evt.getPropertyName())) { this.elapsedTimeField.setValue((Integer) value); } else if (DATA_RECEIVED_PROPERTY.equals(evt.getPropertyName())) { - this.dataReceivedField.setValue((Long) value); + this.dataReceivedField.setValue(formatter.format((Double) value)); } else if (EVENT_NUMBER_PROPERTY.equals(evt.getPropertyName())) { this.eventNumberField.setValue((Integer) value); } else if (DATA_RATE_PROPERTY.equals(evt.getPropertyName())) { - this.dataRateField.setValue((Double) value); + this.dataRateField.setValue(formatter.format((Double) value)); + } else if (EVENT_RATE_PROPERTY.equals(evt.getPropertyName())) { + this.eventRateField.setValue(formatter.format((Double) value)); } } } Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/model/ConfigurationModel.java ============================================================================= --- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/model/ConfigurationModel.java (original) +++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/model/ConfigurationModel.java Tue Jan 27 10:34:17 2015 @@ -16,8 +16,6 @@ // FIXME: When the set methods are called, e.g. from GUI updates, this triggers // a property change event that pushes the values back to the GUI again. // FIXME: Should check if property exists in set methods before retrieving old value for all set methods. -// FIXME: Should use objects instead of primitive types so that null can be used (e.g. for run number etc.). -// TODO: How to handle null values? public final class ConfigurationModel extends AbstractModel { Configuration config; Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/model/RunModel.java ============================================================================= --- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/model/RunModel.java (original) +++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/model/RunModel.java Tue Jan 27 10:34:17 2015 @@ -17,6 +17,7 @@ public final static String DATA_RECEIVED_PROPERTY = "DataReceived"; // updated on the fly, in bytes public final static String EVENT_NUMBER_PROPERTY = "EventNumber"; // current event number public final static String DATA_RATE_PROPERTY = "DataRate"; // data rate in megabytes per second + public final static String EVENT_RATE_PROPERTY = "EventRate"; // event rate per second static final String[] properties = new String[] { RUN_NUMBER_PROPERTY, @@ -27,26 +28,24 @@ ELAPSED_TIME_PROPERTY, DATA_RECEIVED_PROPERTY, EVENT_NUMBER_PROPERTY, - DATA_RATE_PROPERTY + DATA_RATE_PROPERTY, + EVENT_RATE_PROPERTY }; - int runNumber; + Integer runNumber; Date startDate; Date endDate; - int runLength; - int totalEvents; - int eventsReceived; - int elapsedTime; - long dataReceived; - int eventNumber; - double dataRate; + Integer runLength; + Integer totalEvents; + Integer eventsReceived; + Integer elapsedTime; + Double dataReceived; + Integer eventNumber; + Double dataRate; + Double eventRate; public String[] getPropertyNames() { return properties; - } - - public int getRunNumber() { - return runNumber; } public void setRunNumber(int runNumber) { @@ -55,28 +54,16 @@ this.firePropertyChange(RUN_NUMBER_PROPERTY, oldValue, this.runNumber); } - public Date getStartDate() { - return startDate; - } - public void setStartDate(Date startDate) { Date oldValue = this.startDate; this.startDate = startDate; this.firePropertyChange(START_DATE_PROPERTY, oldValue, this.startDate); } - public Date getEndDate() { - return endDate; - } - public void setEndDate(Date endDate) { Date oldValue = this.endDate; this.endDate = endDate; this.firePropertyChange(END_DATE_PROPERTY, oldValue, this.endDate); - } - - public int getRunLength() { - return runLength; } public void setRunLength(int runLength) { @@ -93,18 +80,10 @@ } } - public int getTotalEvents() { - return totalEvents; - } - public void setTotalEvents(int totalEvents) { int oldValue = this.totalEvents; this.totalEvents = totalEvents; this.firePropertyChange(TOTAL_EVENTS_PROPERTY, oldValue, this.totalEvents); - } - - public int getEventsReceived() { - return eventsReceived; } public void setEventsReceived(int eventsReceived) { @@ -117,27 +96,19 @@ this.setEventsReceived(eventsReceived + 1); } - public int getElapsedTime() { - return elapsedTime; - } - public void setElapsedTime(int elapsedTime) { int oldValue = this.elapsedTime; this.elapsedTime = elapsedTime; this.firePropertyChange(ELAPSED_TIME_PROPERTY, oldValue, this.elapsedTime); } - public long getDataReceived() { - return dataReceived; - } - - public void setDataReceived(long dataReceived) { - long oldValue = this.dataReceived; + public void setDataReceived(double dataReceived) { + double oldValue = this.dataReceived; this.dataReceived = dataReceived; this.firePropertyChange(DATA_RECEIVED_PROPERTY, oldValue, this.dataReceived); } - public void addDataReceived(long addDataReceived) { + public void addDataReceived(double addDataReceived) { this.setDataReceived(dataReceived + addDataReceived); } @@ -152,11 +123,13 @@ this.dataRate = dataRate; this.firePropertyChange(DATA_RATE_PROPERTY, oldValue, this.dataRate); } + + public void setEventRate(double eventRate) { + double oldValue = this.eventRate; + this.eventRate = eventRate; + this.firePropertyChange(EVENT_RATE_PROPERTY, oldValue, this.eventRate); + } - public double getDataRate() { - return dataRate; - } - public void reset() { setDataReceived(0); setElapsedTime(0); @@ -167,4 +140,4 @@ setStartDate(null); setTotalEvents(0); } -} +}