Print

Print


Commit in lcio on MAIN
build.xml+13-51.20 -> 1.21
config/lcio.properties+10-21.51 -> 1.52
src/java/hep/lcio/util/CommandHandler.java+67added 1.1
                      /CommandLineTool.java+199added 1.1
                      /MergeCommandHandler.java+131added 1.1
                      /MergeTestEvents.java+66added 1.1
                      /MergeUtil.java+480added 1.1
tools/commons-cli-1.0.jar[binary]added 1.1
     /commons-lang-2.1.jar[binary]added 1.1
+966-7
7 added + 2 modified, total 9 files
JM: Committing Merge command (for Norman's inspection)

lcio
build.xml 1.20 -> 1.21
diff -u -r1.20 -r1.21
--- build.xml	28 Mar 2006 18:21:30 -0000	1.20
+++ build.xml	24 Apr 2006 22:08:33 -0000	1.21
@@ -5,7 +5,7 @@
 <!--     this file is used for FreeHEP and WIRED                             -->
 <!--                                                                         -->
 <!-- Author: Mark Donszelmann                                                -->
-<!-- Version: $Id: build.xml,v 1.20 2006/03/28 18:21:30 gaede Exp $    -->
+<!-- Version: $Id: build.xml,v 1.21 2006/04/24 22:08:33 jeremy Exp $    -->
 <!--                                                                         -->
 <!-- ======================================================================= -->
 
@@ -53,7 +53,7 @@
   <!-- Initialization, setup of commands, check                            -->
   <!-- =================================================================== -->
   <target name="init">
-
+    
     <taskdef name="junit"               classname="org.apache.tools.ant.taskdefs.optional.junit.JUnitTask"/>
 
     <taskdef name="freehep.ant"         classname="org.freehep.ant.FreeHepAnt"/>
@@ -579,10 +579,18 @@
     <junit printsummary="yes" fork="no">
       <classpath>
         <pathelement path="." />
-      </classpath>
+      	<pathelement path="${test.classpath}" />
+      </classpath>    	
       <formatter type="plain" />
-      <test name="org.freehep.graphicsio.test.TestSuite" />
+      <test name="hep.lcio.test.RandomEventTest" />
+      <!--<test name="org.freehep.graphicsio.test.TestSuite" />-->
     </junit>
+    <junitreport todir="${test.output}">
+      <fileset dir="${test.output}">
+        <include name="TEST-*.xml"/>
+      </fileset>
+      <report format="${test.format}" todir="${test.html}"/>
+    </junitreport>
   </target>
 
   <!-- =================================================================== -->
@@ -905,6 +913,6 @@
     <freehep.ant jars="${jlinks}" args="jlink.clean"/>
     <freehep.ant args="dist.clean"/>
   </target>
-
+  
 </project>
 

lcio/config
lcio.properties 1.51 -> 1.52
diff -u -r1.51 -r1.52
--- lcio.properties	8 Mar 2006 09:57:26 -0000	1.51
+++ lcio.properties	24 Apr 2006 22:08:33 -0000	1.52
@@ -1,8 +1,10 @@
 # ANT property file for LCIO
 #
 # Author: Mark Donszelmann
-# Version: $Id: lcio.properties,v 1.51 2006/03/08 09:57:26 gaede Exp $
+# Version: $Id: lcio.properties,v 1.52 2006/04/24 22:08:33 jeremy Exp $
 #
+debug=true
+
 jars=java
 wars=
 jlinks=
@@ -17,7 +19,13 @@
 #jar.excludes=**/test/**
 jar.suffixes=*.class, *.dtd, *.txt, *.gif, *.properties
 
-classpath=src/java;tools/sio.jar;tools/saxpath.jar;tools/jel.jar;tools/jdom.jar;tools/jaxen-core.jar;tools/jaxen-jdom.jar
+# test properties --JM
+test.output=./reports
+test.html=./reports/html
+test.classpath=lib/lcio.jar;tools/sio.jar;tools/commons-cli-1.0.jar;tools/commons-lang-2.1.jar
+test.format=frames
+
+classpath=src/java;tools/sio.jar;tools/saxpath.jar;tools/jel.jar;tools/jdom.jar;tools/jaxen-core.jar;tools/jaxen-jdom.jar;tools/commons-cli-1.0.jar;tools/commons-lang-2.1.jar
 srcpath=src/java
 exp.srcpath=
 

lcio/src/java/hep/lcio/util
CommandHandler.java added at 1.1
diff -N CommandHandler.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ CommandHandler.java	24 Apr 2006 22:08:34 -0000	1.1
@@ -0,0 +1,67 @@
+package hep.lcio.util;
+
+/**
+ * 
+ * A CommandHandler handles the command-line options for a
+ * single command in the CommandLineTool.
+ * 
+ * @author jeremym
+ * @version $Id: CommandHandler.java,v 1.1 2006/04/24 22:08:34 jeremy Exp $
+ */
+
+public abstract class CommandHandler 
+{
+	String name;
+	String description;
+	
+	/**
+	 * CommandHandler ctor.
+	 * @param name The string that invokes this command.
+	 * @param description The description of this command.
+	 */
+	public CommandHandler(String name, String description)
+	{
+		this.name = name;
+		this.description = description;
+	}
+	
+	/**
+	 * Ctor with default description.
+	 * @param name The string that invokes this command.	
+	 */
+	public CommandHandler(String name)
+	{
+		this.name = name;
+		this.description = "NONE";
+	}
+	
+	/**
+	 * Get the name of this command.
+	 * @return A String of the name of this command.
+	 */
+	public String getName()
+	{
+		return this.name;
+	}
+	
+	/**
+	 * Get the description of this command.
+	 * @return A String of the description of this command.
+	 */
+	public String getDescription()
+	{
+		return this.description;
+	}
+	
+	/** 
+	 * Parse this command's options from the command line. 
+	 * @param argv Raw options array following after the command string. 
+	 */
+    public abstract void parse(String[] argv) throws Exception;
+    
+    /** 
+     * Execute the command from parsed args.
+     * @param Execute the command with arguments built parse. 
+     */
+    public abstract void execute() throws Exception;
+}

lcio/src/java/hep/lcio/util
CommandLineTool.java added at 1.1
diff -N CommandLineTool.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ CommandLineTool.java	24 Apr 2006 22:08:34 -0000	1.1
@@ -0,0 +1,199 @@
+package hep.lcio.util; 
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+//import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.HelpFormatter;
+//import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+//import org.apache.commons.cli.Parser;
+//import org.apache.commons.cli.PosixParser;
+
+/**
+ * CommandLineTool provides a command-line interface
+ * to LCIO utilities, similar to how the cvs command 
+ * works.
+ * 
+ * lcio [global_options] [command] [command_options]
+ * 
+ * @see hep.lcio.util.Compare compare
+ * @see hep.lcio.util.Concat concat
+ * @see hep.lcio.util.Headers head
+ * @see hep.lcio.util.MergeCommandHandler merge
+ * @see hep.lcio.util.PrintEvent print
+ * @see hep.lcio.util.SioDump siodump
+ * @see hep.lcio.util.Split split
+ * 
+ * @author jeremym
+ * @version $Id: CommandLineTool.java,v 1.1 2006/04/24 22:08:34 jeremy Exp $
+ */
+// TODO: Implement global options.
+public class CommandLineTool
+{
+	private Map handlers = new HashMap();
+	private String command;
+//	private Parser parser = new PosixParser();
+	private Options options = new Options();
+	
+	public CommandLineTool()
+	{
+		//System.out.println("CommandLineTool");
+
+		registerOptions();
+		registerHandlers();
+	}	
+	
+	// main entry point.
+	public static void main(String[] args) throws Exception
+	{
+		//System.err.println("main");
+
+		CommandLineTool cl = new CommandLineTool();
+
+		// try {
+		cl.parse(args);
+		// }
+		// catch (Exception e)
+		// {
+		// throw new RuntimeException("Problem parsing args.",e);
+		// }
+	}
+
+	// Register the default CommandHandlers.
+	private void registerHandlers()
+	{
+		// addCommandHandler("compare", Compare)
+		// addCommandHandler("concat", Concat);
+		// addCommandHandler("printevent", PrintEvent);
+		// addCommandHandler("header", HeaderScan);
+		addCommandHandler(new MergeCommandHandler());
+		// addCommandHandler("siodump", SioDump);
+		// addCommandHandler("split", Split);
+	}
+
+	// Register global options. Sub-commands have their own option set.
+	private void registerOptions()
+	{
+//		Option opt = new Option("h", false, "print lcio command-line tool usage");
+//		options.addOption(opt);
+
+//		opt = new Option("v", false, "set the verbosity");
+//		opt.setArgs(1);
+//		options.addOption(opt);
+	}
+
+	// Set the name of the active sub-command.
+	public void setCommand(String command)
+	{
+		this.command = command;
+	}
+
+	// Get the name of the active sub-command.
+	public String getCommand()
+	{
+		return this.command;
+	}
+
+	// Parse the command line for global options.  
+	// Then find and execute the appropriate CommandHandler.
+	public void parse(String[] args) throws Exception
+	{
+		int icmd = scanForCommand(args);
+
+		if (icmd == -1)
+		{
+			printUsage(true);
+		}
+
+		// Set the command to execute.
+		setCommand(args[icmd]);
+
+		System.out.println("command: " + getCommand());
+
+		// Get a command handler for this command string.
+		CommandHandler handler = getCommandHandler(getCommand());
+
+		// Global arguments.
+		/*
+		int nglob = icmd - 1;
+		String[] globargv = new String[0];
+		if (nglob > 0)
+		{
+			globargv = new String[nglob];
+			System.arraycopy(args, 0, globargv, 0, nglob);
+			for (int i = 0; i < globargv.length; i++)
+			{
+				System.out.println("globargv[" + i + "]=" + globargv[i]);
+			}
+		}
+		*/
+
+		// Arguments are passed verbatim to the subcommand.
+		int ncmd = args.length - (icmd + 1);
+		String[] cmdargv = new String[ncmd];
+		System.arraycopy(args, icmd + 1, cmdargv, 0, ncmd);
+		for (int i = 0; i < cmdargv.length; i++)
+		{
+			System.out.println("cmdargv[" + i + "]=" + cmdargv[i]);
+		}
+
+		// Parse global options.
+		//CommandLine cl = parser.parse(options, globargv);
+
+		// Pass the subcommand the command line options
+		// with globals stripped out.
+		handler.parse(cmdargv);
+
+		// Execute the CommandHandler.
+		handler.execute();
+	}
+
+	// Add a class to handle a command string.
+	public void addCommandHandler(CommandHandler handler)
+	{
+		handlers.put(handler.getName(), handler);
+	}
+
+	// Get a CommandHandler from the command string.
+	public CommandHandler getCommandHandler(String command) throws Exception
+	{
+		return (CommandHandler) handlers.get(command);
+	}
+
+	// Scan the argv for an input command string, e.g. "merge", etc.
+	private int scanForCommand(String[] argv)
+	{
+		for (int i = 0; i < argv.length; i++)
+		{
+			if (handlers.get(argv[i]) != null)
+			{
+				//System.err.println("found " + argv[i] + " @ idx " + i);
+				return i;
+			}
+		}
+		return -1;
+	}
+
+	// Print usage using CLI.
+	public void printUsage(boolean doExit)
+	{
+		HelpFormatter help = new HelpFormatter();
+
+		StringBuffer s = new StringBuffer();
+
+		for (Iterator it = handlers.keySet().iterator(); it.hasNext();)
+		{
+			s.append((String) it.next() + '\n');
+		}
+
+		help.printHelp("LcioCommandLineTool", "Commands:\n" + s.toString(),
+				options, "");
+
+		if (doExit)
+		{
+			System.exit(0);
+		}
+	}
+}
\ No newline at end of file

lcio/src/java/hep/lcio/util
MergeCommandHandler.java added at 1.1
diff -N MergeCommandHandler.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ MergeCommandHandler.java	24 Apr 2006 22:08:34 -0000	1.1
@@ -0,0 +1,131 @@
+package hep.lcio.util;
+
+import java.io.File;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.Parser;
+import org.apache.commons.cli.PosixParser;
+
+/**
+ * This is the CommandHandler for the merge utility.
+ * It handles command-line options and passes them
+ * to methods in MergeUtil.
+ * 
+ * @author jeremym
+ * @version $Id: MergeCommandHandler.java,v 1.1 2006/04/24 22:08:34 jeremy Exp $
+ */
+public class MergeCommandHandler extends CommandHandler
+{
+	Parser parser = new PosixParser();
+	Options options = new Options();
+	File outfile;
+	File[] infiles;
+	float dt = 0;
+	boolean breakOnSingleEOF = false;
+	int maxevents = Integer.MAX_VALUE;
+	int ntoread = 1;
+	boolean incrTime = false;
+
+	/** 
+	 * MergeCommandHandler ctor. 
+	 */
+	MergeCommandHandler()
+	{
+		// Call CommandHandler ctor.
+		super("merge", "Merge LCIO events together.");
+
+		// Setup options for the merge command.
+		options = createMergeOptions();
+	}
+
+	/**
+	 * Creates the CLI options for the merge command.
+	 * @return Options for the merge command.
+	 */
+	private Options createMergeOptions()
+	{
+		Options options = new Options();
+
+		Option opt = new Option("o", false, "set the output file");
+		opt.setArgs(1);
+		options.addOption(opt);
+
+		opt = new Option("i", false, "add an input file");
+		opt.setArgs(1);
+		options.addOption(opt);
+
+		opt = new Option("t", true, "set delta time (NS)");
+		opt.setArgs(1);
+		options.addOption(opt);
+
+		opt = new Option("d", false, "increment t after each overlay event");
+		opt.setArgs(1);
+		options.addOption(opt);
+
+		opt = new Option("n", true, "set maximum number of events");
+		opt.setArgs(1);
+		options.addOption(opt);
+
+		opt = new Option("c", true, "continue when one of the input files runs out of events (default is stop processing)");
+		options.addOption(opt);
+
+		opt = new Option("e", true, "set number of events at a time to merge in from each input file (default is 1)");
+
+		return options;
+	}
+
+	/** 
+	 * Parse the command line options for the merge command using apache CLI.
+	 * @param argv The input arguments for the merge command. 
+	 */
+	public void parse(String[] argv) throws Exception
+	{
+		CommandLine cl = parser.parse(options, argv);
+
+		// Make an input file list.
+		if (cl.hasOption("i"))
+		{	
+			infiles = MergeUtil.createFiles(cl.getOptionValues("i"));
+		}
+
+		// DEBUG
+		System.err.println("outfile=" + cl.getOptionValue("o"));
+
+		// Output file.
+		outfile = new File(cl.getOptionValue("o"));
+
+		// The time delta.
+		if (cl.hasOption("t"))
+		{
+			dt = Float.parseFloat(cl.getOptionValue("t"));
+		}
+
+		// Set whether to break on a single EOF from input files.
+		if (cl.hasOption("c"))
+		{
+			breakOnSingleEOF = false;
+		}
+
+		// Set max events.
+		if (cl.hasOption("n"))
+		{
+			maxevents = Integer.parseInt(cl.getOptionValue("n"));
+		}
+
+		// Set whether to increment the time delta after each event overlay.
+		if (cl.hasOption("d"))
+		{
+			incrTime = true;
+		}
+	}
+
+	/** 
+	 * Execute the merge command with current arguments. 
+	 */
+	public void execute() throws Exception
+	{
+		MergeUtil.mergeFiles(outfile, infiles, ntoread, maxevents, dt, incrTime);
+	}
+}
\ No newline at end of file

lcio/src/java/hep/lcio/util
MergeTestEvents.java added at 1.1
diff -N MergeTestEvents.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ MergeTestEvents.java	24 Apr 2006 22:08:34 -0000	1.1
@@ -0,0 +1,66 @@
+package hep.lcio.util;
+
+import hep.lcio.event.LCEvent;
+import hep.lcio.event.LCIO;
+import hep.lcio.implementation.event.ILCCollection;
+import hep.lcio.implementation.event.ILCEvent;
+import hep.lcio.implementation.event.IMCParticle;
+import hep.lcio.implementation.event.ISimCalorimeterHit;
+import hep.lcio.implementation.event.ISimTrackerHit;
+import hep.lcio.implementation.io.LCFactory;
+import hep.lcio.io.LCReader;
+import hep.lcio.io.LCWriter;
+
+/**
+ * Create some very simple test events for the Merge utility.
+ * 
+ * @author jeremym
+ *
+ */
+public class MergeTestEvents
+{
+	public static void main(String[] argv) throws Exception 
+	{ 		
+		System.out.println("MergeTestEvents.main");
+		
+		LCWriter writer = 
+			LCFactory.getInstance().createLCWriter();
+		
+		writer.open("mergetest1", LCIO.WRITE_NEW);		
+
+		ILCEvent event = new ILCEvent();
+		event.setDetectorName("TEST");
+		event.setEventNumber(0);
+		event.setRunNumber(0);
+		event.setTimeStamp(0);
+		
+		ILCCollection coll = new ILCCollection(LCIO.MCPARTICLE);
+		IMCParticle p = new IMCParticle();
+		coll.add(p);
+		event.addCollection(coll, "particles");
+				
+		coll = new ILCCollection(LCIO.SIMCALORIMETERHIT); 
+		ISimCalorimeterHit chit = new ISimCalorimeterHit();
+		chit.addMCParticleContribution(p, (float)1.0, 0, 11);
+		coll.add(chit);
+		event.addCollection(coll, "calhits");
+		
+		coll = new ILCCollection(LCIO.SIMTRACKERHIT);
+		ISimTrackerHit thit = new ISimTrackerHit();
+		thit.setMCParticle(p);
+		coll.add(thit);
+		event.addCollection(coll, "tkrhits");
+		
+		writer.writeEvent(event);
+		writer.close();
+		
+		writer.open("mergetest2", LCIO.WRITE_NEW);
+		writer.writeEvent(event);
+		writer.close();
+		
+		LCReader reader = LCFactory.getInstance().createLCReader();
+		reader.open("mergetest1.slcio");
+		LCEvent checkevent = reader.readNextEvent();
+		System.out.println("read back event: " + checkevent);
+	}
+}

lcio/src/java/hep/lcio/util
MergeUtil.java added at 1.1
diff -N MergeUtil.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ MergeUtil.java	24 Apr 2006 22:08:34 -0000	1.1
@@ -0,0 +1,480 @@
+package hep.lcio.util;
+
+import hep.lcio.event.LCCollection;
+import hep.lcio.event.LCEvent;
+import hep.lcio.event.LCIO;
+import hep.lcio.event.SimCalorimeterHit;
+import hep.lcio.implementation.event.ILCCollection;
+import hep.lcio.implementation.event.ILCEvent;
+import hep.lcio.implementation.event.IMCParticle;
+import hep.lcio.implementation.event.ISimCalorimeterHit;
+import hep.lcio.implementation.event.ISimTrackerHit;
+import hep.lcio.implementation.io.LCFactory;
+import hep.lcio.implementation.sio.SIOEvent;
+import hep.lcio.io.LCReader;
+import hep.lcio.io.LCWriter;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Utility methods for merging LCIO files, events, and collections,
+ * with possible application of time delta.
+ * 
+ * @author jeremym
+ * @version $Id: MergeUtil.java,v 1.1 2006/04/24 22:08:34 jeremy Exp $
+ */
+abstract public class MergeUtil
+{	
+	/** 
+	 * Merge nEventsToRead events from each File in infiles into a single event in outfile,
+	 * until records in infiles are exhausted or maxevents are created. 
+	 * @return The number of combined events created.
+	 * @param outfile Output target file.
+	 * @param infiles Input events to merge in.
+	 * @param nEventsToRead Number of events to read at once into one output event.
+	 * @param maxEventsToWrite Maximum number of output events to create.
+	 * @param dt The time delta.
+	 */
+	public static int mergeFiles( 
+			File outfile, 
+			File[] infiles, 
+			int nEventsToRead, 
+			int maxEventsToWrite, 
+			float dt,
+			boolean incrTime) throws IOException
+	{
+		// Create the writer.
+		LCWriter writer = LCFactory.getInstance().createLCWriter();
+		
+		// Open the writer for the new file containing the merged events.
+		writer.open(outfile.getCanonicalPath(), LCIO.WRITE_NEW);
+
+		// Create the array of LCReaders.
+		LCReader[] readers = createReaders(infiles);
+
+		// Count of total output events.
+		int nevents = 0;
+
+		// File read loop.
+		for (;;)
+		{
+			System.err.println("nevents: " + nevents);
+
+			// Check if max output events is reached.
+			if (nevents > maxEventsToWrite)
+				break;
+
+			// Create the new output event.
+			ILCEvent target = new ILCEvent();
+
+			// First time, the event header needs to
+			// be set from the first LCEvent read.
+			boolean setEventHeader = true;
+
+			// Total events merged in from all sources in this pass.
+			int totmerged = 0;
+
+			// Loop over the readers.
+			for (int i = 0; i < readers.length; i++)
+			{
+				// Get the next reader.
+				LCReader reader = readers[i];
+
+				// Merge ntoread events from this reader into target with delta time of dt.
+				int nmerged = MergeUtil.merge(target, reader, nEventsToRead, setEventHeader, dt, incrTime);
+
+				// DEBUG
+				System.err.println("nmerged: " + nmerged);
+
+				// Increment total merged.
+				totmerged += nmerged;
+
+				// Next time, don't need to set the header.
+				setEventHeader = false;
+			}
+
+			// Write out the combined event if something got merged in.
+			if (totmerged > 0)
+			{
+				//System.err.println("totmerged: " + totmerged);
+
+				writer.writeEvent(target);
+				nevents++;
+			}
+			else
+			{
+				// Done!
+				break;
+			}
+		} // file read loop
+
+		// Close the writer.
+		writer.close();
+
+		// Close the readers.
+		closeReaders(readers);
+		
+		// Return number of events created.
+		return nevents;
+	}
+	
+	/**
+	 * Merge n events read from a reader into a single target event.
+	 * @return Number of events overlayed from overlayEvents reader.
+	 * @param targetEvent target LCEvent to merge events into
+	 * @param overlayEvents LCReader with overlay events to read
+	 * @param ntoread number of events to overlay from overlayEvents
+	 * @param dt delta time to be applied to the sim types
+	 */
+	public static int merge(
+			LCEvent targetEvent, 
+			LCReader overlayEvents, 
+			int ntoread, 			 
+			boolean setEventHeader,
+			float dt,
+			boolean incrTime) throws IOException
+	{
+		// Read the next event from the reader.
+		LCEvent nextOverlayEvent = overlayEvents.readNextEvent();
+
+		// Return 0 if reader is exhausted.
+		if (nextOverlayEvent == null)
+		{
+			return 0;
+		}
+
+		// Set the event header from first event if setEventHeader flag is true.
+		if (setEventHeader)
+		{
+			ILCEvent itargetEvent = (ILCEvent) targetEvent;
+			itargetEvent.setDetectorName(nextOverlayEvent.getDetectorName());
+			itargetEvent.setEventNumber(nextOverlayEvent.getEventNumber());
+			itargetEvent.setRunNumber(nextOverlayEvent.getRunNumber());
+			itargetEvent.setTimeStamp(nextOverlayEvent.getTimeStamp());
+		}
+
+		// Read ntoread events from reader and merge into targetEvent.
+		int nevt = 0;
+		float time = dt;
+		for (; nevt < ntoread && nextOverlayEvent != null; nevt++)
+		{
+			// Merge single overlay event onto targetEvent.
+			overlayEvent((ILCEvent) targetEvent, nextOverlayEvent, dt);
+
+			// Get next event to merge in. (could be null)
+			nextOverlayEvent = overlayEvents.readNextEvent();
+			
+			// Increment the delta time for next event.
+			if (incrTime)
+				time += dt;
+		}
+
+		// Return the number of events that were overlayed.
+		return nevt;
+	}
+		
+	/** 
+	 * Overlay the overlay event onto target event, applying time delta.
+	 * @param targetEvent The event that will be overlayed onto from overlayEvent.
+	 * @param overlayEvent An event to be overlayed onto targetEvent.
+	 * @param dt A delta time to apply to sim types.
+	 */
+	public static void overlayEvent(ILCEvent targetEvent, LCEvent overlayEvent, float dt)
+	{
+		if (overlayEvent.getCollectionNames().length == 0)
+		{
+			// Empty event, nothing to do.
+			return;
+		}
+
+		if (overlayEvent instanceof SIOEvent)
+		{
+			// Turn off readonly mode on overlay event.
+			((SIOEvent) overlayEvent).setReadOnly(false);
+		}
+
+		// Get names of collections already existing in target.
+		String[] tcolls = targetEvent.getCollectionNames();
+
+		// Get names of collections to be merged in.
+		String[] ocolls = overlayEvent.getCollectionNames();
+
+		// Iterate over the overlay collections that will be merged into target.
+		for (int i = 0; i < ocolls.length; i++)
+		{
+			// Get name of this overlay collection.
+			String collname = ocolls[i];
+
+			// Get this overlay collection.
+			LCCollection ocoll = overlayEvent.getCollection(collname);
+
+			// Declare the target collection reference,
+			// which will be either a new collection or
+			// an existing one from the target.
+			LCCollection tcoll = null;
+
+			// Find the index of this overlay collection in the target.
+			int tidx = getCollectionIdx(tcolls, collname);
+
+			// If index is -1, there is no existing collection in the target.
+			if (tidx == -1)
+			{
+				// Create an empty target collection with the overlay collection's settings.
+				tcoll = copy(overlayEvent.getCollection(collname));
+
+				// Add the new collection to the target event.
+				targetEvent.addCollection(tcoll, collname);
+			}
+			else
+			{
+				// Get the existing target collection.
+				tcoll = targetEvent.getCollection(collname);
+			}
+
+			// Handle overlay for each pair of target-overlay collections.
+			overlayCollection(tcoll, ocoll, dt);
+		}
+
+		return;
+	}
+	
+	/**
+	 * overlayCollection overlays the overlayColl onto the targetColl applying dt.
+	 * @param targetColl The target collection to be modified.
+	 * @param overlayColl The overlay collection containing objects to merge into targetColl.
+	 * @param dt A delta time parameter applied to sim types of overlayColl before merge-in.
+	 */
+	public static void overlayCollection(LCCollection targetColl, LCCollection overlayColl, float dt)
+	{
+		String colltype = targetColl.getTypeName();
+
+		// Handle a SimTrackerHit collection.
+		if (colltype.compareTo(LCIO.SIMTRACKERHIT) == 0)
+		{
+			// Loop over hits to merge in.
+			for (int ii = 0; ii < overlayColl.size(); ii++)
+			{
+				// Get the hit from the overlay collection.
+				ISimTrackerHit hit = (ISimTrackerHit) overlayColl.getElementAt(ii);
+
+				// Adjust time.
+				hit.setTime(hit.getTime() + dt);
+
+				// Add the hit to the target collection.
+				targetColl.add(hit);
+			}
+		}
+		// Handle a SimCalorimeterHit collection.
+		else if (colltype.compareTo(LCIO.SIMCALORIMETERHIT) == 0)
+		{
+			// Loop over the overlay hits.
+			for (int ii = 0; ii < overlayColl.size(); ii++)
+			{
+				// Get an overlay hit.
+				ISimCalorimeterHit ohit = (ISimCalorimeterHit) overlayColl.getElementAt(ii);
+
+				// Find a matching hit in target collection.
+				ISimCalorimeterHit thit = findMatching(targetColl, ohit);
+
+				// No matching hits?
+				if (thit == null)
+				{
+					System.out.println("new hit");
+
+					// Copy the overlay hit without MCParticle contributions.
+					thit = copy(ohit);
+
+					// Add the hit to the target collection.
+					targetColl.addElement(thit);
+				}
+
+				// Apply MCParticle contributions from overlay to target.
+				addMCParticleContributions(thit, ohit, dt);
+			}
+		}
+		// Handle an MCParticle collection.
+		else if (colltype.compareTo(LCIO.MCPARTICLE) == 0)
+		{
+			for (int ii = 0; ii < overlayColl.size(); ii++)
+			{
+				IMCParticle p = (IMCParticle) overlayColl.getElementAt(ii);
+
+				// Apply dt.
+				p.setTime(p.getTime() + dt);
+
+				targetColl.add(p);
+			}
+		}
+		// Handle a default collection.
+		else
+		{
+			for (int ii = 0; ii < overlayColl.size(); ii++)
+			{
+				targetColl.add(overlayColl.getElementAt(ii));
+			}
+		}
+
+	}
+	
+	/** 
+	 * Find a SimCalorimeterHit in coll with matching cellId0, cellId1. 
+	 * @return The first match of hit in coll.
+	 * @param Collection of type SIMCALORIMETERHIT.
+	 * @param hit Matching hit to be searched for in coll.
+	 */
+	public static ISimCalorimeterHit findMatching(LCCollection coll, SimCalorimeterHit hit)
+	{	
+		ISimCalorimeterHit match = null;
+
+		for (int i = 0; i < coll.size(); i++)
+		{
+			ISimCalorimeterHit checkhit = (ISimCalorimeterHit) coll.getElementAt(i);
+			if ((checkhit.getCellID0() == hit.getCellID0() && checkhit.getCellID1() == hit.getCellID1()) || checkhit == hit)
+			{
+				match = checkhit;
+				break;
+			}
+		}
+		
+		return match;
+	}
+
+	/** 
+	 * Find the given name in collnames.
+	 * @return The index of name in collnames or -1 if not found.
+	 * @param collnames A list of collection names.
+	 * @param name A collection name to find in collnames. 
+	 */
+	public static int getCollectionIdx(String[] collnames, String name)
+	{
+		int idx = -1;
+		for (int i = 0; i < collnames.length; i++)
+		{
+			if (collnames[i].compareTo(name) == 0)
+			{
+				idx = i;
+				break;
+			}
+		}
+		return idx;
+	}
+
+	/** 
+	 * Add MCParticle contributions from an overlay hit to a target hit. 
+	 * @param target Hit that receives MCParticle contributions.
+	 * @param hit Hit containing MCParticle contributions to be copied.
+	 * @param dt Delta time to apply to contributions.
+	 */
+	public static void addMCParticleContributions(ISimCalorimeterHit target, SimCalorimeterHit hit, float dt)
+	{
+
+		System.err.println("nmcp: " + hit.getNMCContributions());
+		for (int j = 0; j < hit.getNMCContributions(); j++)
+		{
+			// PDGID might not be set.
+			int pdgid = 0;
+			try
+			{
+				pdgid = target.getPDGCont(j);
+			}
+			catch (Exception e)
+			{
+			}
+
+			// Add this MCContrib to the existing hit, applying dt.
+			target.addMCParticleContribution(hit.getParticleCont(j), hit.getEnergyCont(j), hit.getTimeCont(j) + dt, pdgid);
+		}
+	}
+
+	/** 
+	 * Shallow copy a SimCalorimeterHit.  
+	 * Do not copy MCParticle contributions.
+	 * @return A copy of hit. 
+	 * @param hit The hit to be copied.
+	 */
+	private static ISimCalorimeterHit copy(SimCalorimeterHit hit)
+	{
+		ISimCalorimeterHit newhit = new ISimCalorimeterHit();
+		newhit.setCellID0(hit.getCellID0());
+		newhit.setCellID1(hit.getCellID1());
+		newhit.setPosition(hit.getPosition());
+		return newhit;
+	}
+
+	/** 
+	 * Shallow copy an LCCollection.  
+	 * Do not copy LCObject members.
+	 * @return A copy of collection. 
+	 * @param coll The LCCollection to be copied.
+	 */
+	private static ILCCollection copy(LCCollection coll)
+	{
+		ILCCollection newcoll = new ILCCollection(coll.getTypeName());
+		newcoll.setDefault(coll.isDefault());
+		newcoll.setFlag(coll.getFlag());
+		newcoll.setParameters(coll.getParameters());
+		newcoll.setSubset(coll.isSubset());
+		newcoll.setTransient(coll.isTransient());
+
+		return newcoll;
+	}
+	
+	/** 
+	 * Create an array of LCReaders to be read in parallel.
+	 * @return Array of open LCReaders.
+	 * @param Array of input files. 
+	 */
+	public static LCReader[] createReaders(File[] infiles) throws IOException
+	{
+		// Make a reader for each input event.		
+		LCReader[] readers = new LCReader[infiles.length];
+		for (int i = 0; i < infiles.length; i++)
+		{
+			// Create a new reader.
+			readers[i] = LCFactory.getInstance().createLCReader();
+
+			// Open the reader for this file.
+			readers[i].open(((File) infiles[i]).getCanonicalPath());
+		}
+		return readers;
+	}
+
+	/** 
+	 * Close all of the readers.
+	 * @param readers Array of LCReaders to be closed. 
+	 */
+	public static void closeReaders(LCReader[] readers) throws IOException
+	{
+		for (int i = 0; i < readers.length; i++)
+		{
+			try
+			{
+				readers[i].close();
+			}
+			catch (Throwable t)
+			{
+				// Ignore errors on close.
+			}
+		}
+	}
+	
+	/**
+	 * Return an array of files from an array of file paths.
+	 * @param fstr Array of file paths.
+	 * @return Array of File objects.
+	 */
+	public static File[] createFiles(String[] fstr)
+	{
+		File[] infiles = new File[fstr.length];
+		for (int i = 0; i < fstr.length; i++)
+		{
+			String ifile = (String) fstr[i];
+			infiles[i] = new File(ifile);
+
+			// DEBUG
+			//System.out.println("added input file: " + ifile);
+		}
+		return infiles;
+	}
+}
\ No newline at end of file
CVSspam 0.2.8