Print

Print


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