Author: [log in to unmask]
Date: Mon Mar 23 16:23:56 2015
New Revision: 2509
Log:
Add first pass at EPICS data parsing from EVIO. (This will be moved to another module at some point.)
Added:
java/trunk/evio/src/main/java/org/hps/evio/epics/
java/trunk/evio/src/main/java/org/hps/evio/epics/EpicsEvioProcessor.java
java/trunk/evio/src/main/java/org/hps/evio/epics/EpicsGenericObject.java
java/trunk/evio/src/main/java/org/hps/evio/epics/EpicsScalarData.java
java/trunk/evio/src/test/java/org/hps/evio/epics/
java/trunk/evio/src/test/java/org/hps/evio/epics/EpicsScalarDataTest.java
Modified:
java/trunk/evio/pom.xml
Modified: java/trunk/evio/pom.xml
=============================================================================
--- java/trunk/evio/pom.xml (original)
+++ java/trunk/evio/pom.xml Mon Mar 23 16:23:56 2015
@@ -19,6 +19,10 @@
<dependency>
<groupId>org.hps</groupId>
<artifactId>hps-tracking</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.hps</groupId>
+ <artifactId>hps-record-util</artifactId>
</dependency>
</dependencies>
<build>
Added: java/trunk/evio/src/main/java/org/hps/evio/epics/EpicsEvioProcessor.java
=============================================================================
--- java/trunk/evio/src/main/java/org/hps/evio/epics/EpicsEvioProcessor.java (added)
+++ java/trunk/evio/src/main/java/org/hps/evio/epics/EpicsEvioProcessor.java Mon Mar 23 16:23:56 2015
@@ -0,0 +1,55 @@
+package org.hps.evio.epics;
+
+import org.hps.record.evio.EvioEventConstants;
+import org.hps.record.evio.EvioEventProcessor;
+import org.jlab.coda.jevio.BaseStructure;
+import org.jlab.coda.jevio.EvioEvent;
+
+/**
+ * This is an EVIO event processor that will read EPICS events (event tag 31)
+ * and turn them into {@link EpicsScalarData} objects.
+ *
+ * @author Jeremy McCormick <[log in to unmask]>
+ */
+public final class EpicsEvioProcessor extends EvioEventProcessor {
+
+ public void process(EvioEvent evio) {
+
+ if (evio.getHeader().getTag() != EvioEventConstants.EPICS_EVENT_TAG) {
+ // Just silently skip these events because otherwise too many error messages might print.
+ return;
+ }
+
+ System.out.println("Epics EVIO event " + evio.getEventNumber());
+ System.out.println("Dumping EPICS event ...");
+ System.out.println(evio.toXML());
+
+ // Find the bank with the EPICS information.
+ BaseStructure epicsBank = null;
+ BaseStructure topBank = evio.getChildrenList().get(0);
+ System.out.println("got top bank: " + topBank.getHeader().getTag());
+ for (BaseStructure childBank : topBank.getChildrenList()) {
+ System.out.println("found child bank tag: " + childBank.getHeader().getTag());
+ if (childBank.getHeader().getTag() == EvioEventConstants.EPICS_BANK_TAG) {
+ System.out.println("found EPICS bank tag: " + childBank.getHeader().getTag());
+ epicsBank = childBank;
+ break;
+ }
+ }
+
+ if (epicsBank != null) {
+ System.out.println("found EPICS bank with tag " + epicsBank.getHeader().getTag());
+ String epicsData = epicsBank.getStringData()[0];
+ System.out.println("dumping EPICS string data ...");
+ System.out.println(epicsData);
+
+ EpicsScalarData data = new EpicsScalarData();
+ data.fromString(epicsData);
+
+ System.out.println("parsed EPICS data ...");
+ System.out.println(data.toString());
+ } else {
+ System.out.println("did not find EPICS data bank in event");
+ }
+ }
+}
Added: java/trunk/evio/src/main/java/org/hps/evio/epics/EpicsGenericObject.java
=============================================================================
--- java/trunk/evio/src/main/java/org/hps/evio/epics/EpicsGenericObject.java (added)
+++ java/trunk/evio/src/main/java/org/hps/evio/epics/EpicsGenericObject.java Mon Mar 23 16:23:56 2015
@@ -0,0 +1,56 @@
+package org.hps.evio.epics;
+
+import org.lcsim.event.GenericObject;
+
+/**
+ * This is an implementation of GenericObject for reading and writing EPICS data.
+ * There is no functionality here. Users that need this data in their <code>Driver</code>
+ * classes should instead use {@link EpicsScalarData#read(org.lcsim.event.EventHeader)}
+ * to create the class with the actual API.
+ *
+ * @author Jeremy McCormick <[log in to unmask]>
+ */
+final class EpicsGenericObject implements GenericObject {
+
+ String[] keys;
+ double[] values;
+
+ @Override
+ public int getNInt() {
+ return 0;
+ }
+
+ @Override
+ public int getNFloat() {
+ return 0;
+ }
+
+ @Override
+ public int getNDouble() {
+ return values.length;
+ }
+
+ @Override
+ public int getIntVal(int index) {
+ return 0;
+ }
+
+ @Override
+ public float getFloatVal(int index) {
+ return 0;
+ }
+
+ @Override
+ public double getDoubleVal(int index) {
+ return values[index];
+ }
+
+ @Override
+ public boolean isFixedSize() {
+ return false;
+ }
+
+ public String getKey(int index) {
+ return keys[index];
+ }
+}
Added: java/trunk/evio/src/main/java/org/hps/evio/epics/EpicsScalarData.java
=============================================================================
--- java/trunk/evio/src/main/java/org/hps/evio/epics/EpicsScalarData.java (added)
+++ java/trunk/evio/src/main/java/org/hps/evio/epics/EpicsScalarData.java Mon Mar 23 16:23:56 2015
@@ -0,0 +1,175 @@
+package org.hps.evio.epics;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.GenericObject;
+
+/**
+ * <p>
+ * This is an API for reading and writing EPICS scalar data to LCIO events,
+ * as well as parsing the scalar data from a CDATA section of an EVIO string
+ * data bank.
+ * <p>Sample data:<br/>
+ * <pre>
+ * 2010.350952 MBSY2C_energy
+ * 0.000000 PSPECIRBCK
+ * 2.190000 HPS:LS450_2:FIELD
+ * -8974.000000 HPS:LS450_1:FIELD
+ * 2400.000000 MTIRBCK
+ * 3.882200 VCG2C21
+ * 4.579233 VCG2C21A
+ * 6.799115 VCG2C24A
+ * 6.552529 VCG2H00A
+ * 5.429465 VCG2H01A
+ * 5.741360 VCG2H02A
+ * -0.069630 scaler_calc1
+ * 0.000000 scalerS12b
+ * 0.000000 scalerS13b
+ * 0.000000 scalerS14b
+ * 0.000000 scalerS15b
+ * 0.000000 hallb_IPM2C21A_XPOS
+ * 0.000000 hallb_IPM2C21A_YPOS
+ * 0.000000 hallb_IPM2C21A_CUR
+ * 0.000000 hallb_IPM2C24A_XPOS
+ * 0.000000 hallb_IPM2C24A_YPOS
+ * 0.000000 hallb_IPM2C24A_CUR
+ * 0.000000 hallb_IPM2H00_XPOS
+ * 0.000000 hallb_IPM2H00_YPOS
+ * 0.000000 hallb_IPM2H00_XPOS
+ * 0.000000 hallb_IPM2H00_XPOS
+ * 0.000000 hallb_IPM2H00_CUR
+ * 0.000000 hallb_IPM2H02_YPOS
+ * 0.000000 hallb_IPM2H02_XPOS
+ * </pre>
+ *
+ * @author Jeremy McCormick <[log in to unmask]>
+*/
+// TODO: This API needs to be accessible to recon and analysis modules.
+public final class EpicsScalarData extends LinkedHashMap<String, Double> {
+
+ // Used in collection parameter map as name of the key list.
+ static final String EPICS_SCALAR_NAMES = "EPICS_SCALAR_NAMES";
+
+ // Default collection name in the LCIO event.
+ static final String DEFAULT_COLLECTION_NAME = "EpicsScalarData";
+
+ // Dummy collection parameter maps to try and make LCIO happy.
+ static final Map<String, int[]> DUMMY_INT_MAP = new HashMap<String, int[]>();
+ static final Map<String, float[]> DUMMY_FLOAT_MAP = new HashMap<String, float[]>();
+
+ /**
+ * Convert this object to a string.
+ */
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ for (Entry<String, Double> entry : this.entrySet()) {
+ sb.append(entry.getKey() + " " + entry.getValue() + '\n');
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Parse a raw data string from the EVIO data bank and
+ * turn it into a list of keys and values within this object.
+ * @param rawData The raw data in the form of a string.
+ */
+ void fromString(String rawData) {
+ String lines[] = rawData.split("\\r?\\n");
+ for (String line : lines) {
+ String trimmed = line.trim();
+ if (trimmed.length() == 0) {
+ continue;
+ }
+ String[] data = trimmed.split(" ");
+ Double value = Double.parseDouble(data[0]);
+ String key = data[1];
+ System.out.println("adding key, value: " + data[1] + " " + data[0]);
+ put(key, value);
+ }
+ }
+
+ /**
+ * Convert this object into a {@link org.lcsim.event.GenericObject}
+ * that can be written into an LCIO collection.
+ * @return The GenericObject representing this data.
+ */
+ EpicsGenericObject toGenericObject() {
+ EpicsGenericObject newObject = new EpicsGenericObject();
+ newObject.keys = new String[this.size()];
+ newObject.values = new double[this.size()];
+ int index = 0;
+ for (String key : this.keySet()) {
+ newObject.keys[index] = key;
+ newObject.values[index] = this.get(key);
+ index++;
+ }
+ return newObject;
+ }
+
+ /**
+ * Given a list of keys, read the double values from the
+ * {@link org.lcsim.event.GenericObject} into the map.
+ * @param object
+ * @param keys
+ */
+ void fromGenericObject(GenericObject object, String[] keys) {
+ for (int index = 0; index < keys.length; index++) {
+ this.put(keys[index], object.getDoubleVal(index));
+ }
+ }
+
+ /**
+ * Write this object into an LCIO event under the given collection name.
+ * @param event The LCIO event.
+ * @param collectionName The name of the collection in the event.
+ */
+ void write(EventHeader event, String collectionName) {
+ List<GenericObject> collection = new ArrayList<GenericObject>();
+ EpicsGenericObject object = this.toGenericObject();
+ collection.add(object);
+ Map<String, String[]> stringMap = new HashMap<String, String[]>();
+ stringMap.put(EPICS_SCALAR_NAMES, object.keys);
+ event.put(collectionName, collection, GenericObject.class, 0, DUMMY_INT_MAP, DUMMY_FLOAT_MAP, stringMap);
+ }
+
+ /**
+ * Write this object into an LCIO event using the default collection name.
+ * @param event The LCIO event.
+ */
+ void write(EventHeader event) {
+ write(event, DEFAULT_COLLECTION_NAME);
+ }
+
+ /**
+ * Read data into this object from an LCIO event from the given collection name.
+ * @param event The LCIO event.
+ * @param collectionName The collection name.
+ * @return The EPICS data from the LCIO event.
+ */
+ EpicsScalarData read(EventHeader event, String collectionName) {
+ List<GenericObject> collection = event.get(GenericObject.class, collectionName);
+ @SuppressWarnings("rawtypes")
+ Map stringMap = event.getMetaData(collection).getStringParameters();
+ String[] keys = (String[]) stringMap.get(EPICS_SCALAR_NAMES);
+ EpicsScalarData data = new EpicsScalarData();
+ data.fromGenericObject(collection.get(0), keys);
+ return data;
+ }
+
+ /**
+ * Read data into this object from an LCIO event using the default collection name.
+ * This is the primary method for users to read the EPICS data into their Drivers
+ * in the <code>process</code> method.
+ * @param event The LCIO event.
+ * @return The EPICS data from the event.
+ */
+ public EpicsScalarData read(EventHeader event) {
+ return read(event, DEFAULT_COLLECTION_NAME);
+ }
+}
Added: java/trunk/evio/src/test/java/org/hps/evio/epics/EpicsScalarDataTest.java
=============================================================================
--- java/trunk/evio/src/test/java/org/hps/evio/epics/EpicsScalarDataTest.java (added)
+++ java/trunk/evio/src/test/java/org/hps/evio/epics/EpicsScalarDataTest.java Mon Mar 23 16:23:56 2015
@@ -0,0 +1,28 @@
+package org.hps.evio.epics;
+
+import junit.framework.TestCase;
+
+import org.hps.record.composite.CompositeLoop;
+import org.hps.record.composite.CompositeLoopConfiguration;
+import org.hps.record.enums.DataSourceType;
+import org.hps.record.enums.ProcessingStage;
+
+public class EpicsScalarDataTest extends TestCase {
+
+ public void test() {
+
+ CompositeLoopConfiguration configuration = new CompositeLoopConfiguration();
+ configuration.add(new EpicsEvioProcessor());
+ configuration.setDataSourceType(DataSourceType.EVIO_FILE);
+ configuration.setFilePath("/u1/data/hps/eng_run/hps_004385.evio.0");
+ configuration.setProcessingStage(ProcessingStage.EVIO);
+ configuration.setStopOnEndRun(false);
+ configuration.setStopOnErrors(false);
+
+ CompositeLoop loop = new CompositeLoop();
+ loop.setConfiguration(configuration);
+
+ loop.loop(-1);
+ }
+
+}
|