package hep.io.stdhep;
import hep.io.mcfio.MCFIOBlock;
import hep.io.mcfio.MCFIOEvent;
import hep.io.mcfio.MCFIOReader;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
/**
* A class for reading stdhep files.
* @author Tony Johnson (tonyj@slac.stanford.edu)
* @version $Id: StdhepReader.java 9150 2006-10-16 19:56:07Z tonyj $
*/
public class StdhepReader extends MCFIOReader implements StdhepConstants
{
/**
* Open a stdhep file for reading.
*/
public StdhepReader(String file) throws IOException
{
super(file);
}
/**
* Open a stdhep file for reading.
*/
public StdhepReader(InputStream stream) throws IOException
{
super(stream);
}
/**
* Read the next stdhep record from the file.
* The record may be a begin run, end run, or event record.
*/
public StdhepRecord nextRecord() throws IOException
{
// It is not clear why a stdHEP record would have 0
// blocks, but it does sometimes seem to happen.
for (;;)
{
MCFIOEvent event = super.nextEvent();
int nBlocks = event.getNBlocks();
if (nBlocks == 0)
continue;
if (nBlocks != 1)
throw new IOException("Invalid stdhep record found (NBlocks=" + nBlocks + ")");
return (StdhepRecord) event.getBlock(0);
}
}
/**
* Finds the event with run number and event number specified
* @throws EOFException if the specified event is not found.
*/
public StdhepRecord goToRecord(int runNumber, int eventNumber) throws IOException
{
boolean hasRewound = false;
while (true)
{
try
{
while (true)
{
MCFIOEvent event = super.nextEvent();
if (event.getRunNumber() == runNumber && event.getEventNumber() == eventNumber)
{
// Note, this triggers the event to be read.
int nBlocks = event.getNBlocks();
if (nBlocks == 0)
continue;
if (nBlocks != 1)
throw new IOException("Invalid stdhep record found (NBlocks=" + nBlocks + ")");
return (StdhepRecord) event.getBlock(0);
}
}
}
catch (EOFException x)
{
if (!hasRewound)
{
rewind();
hasRewound = true;
}
else throw x;
}
}
}
/**
* Skip a number of records.
* Attention, skipping events efficiently in stdhep files is unfortunately broken
* due to a bug in the stdhep format. The underlying MCFIO format allows for skipping through
* events quite efficiently, but it is not possible to tell whether a stdhep record is an
* event or a begin or end run record without completely unpacking it, so the following method
* works, but is fairly useless since you cannot tell how many events were actually skipped.
*/
public void skip(int nEvents) throws IOException
{
super.skip(nEvents);
}
/**
* Overrides the createUserBlock from MCFIO to create the
* necessary stdhep records. Override this method to add
* support for your own record types.
*/
protected MCFIOBlock createUserBlock(int id) throws IOException
{
switch (id)
{
case MCFIO_STDHEP:
return new StdhepEvent();
case MCFIO_STDHEPBEG:
return new StdhepBeginRun();
case MCFIO_STDHEPEND:
return new StdhepEndRun();
case MCFIO_STDHEPEV4:
return new StdhepExtendedEvent();
default:
return super.createUserBlock(id);
}
}
}