/*
* #%L
* OME Bio-Formats package for reading and converting biological file formats.
* %%
* Copyright (C) 2005 - 2015 Open Microscopy Environment:
* - Board of Regents of the University of Wisconsin-Madison
* - Glencoe Software, Inc.
* - University of Dundee
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-2.0.html>.
* #L%
*/
package loci.formats.in;
import java.io.IOException;
import java.util.Hashtable;
import java.util.StringTokenizer;
import loci.common.Constants;
import loci.common.RandomAccessInputStream;
/**
* SDTInfo encapsulates the header information for
* Becker & Hickl SPC-Image SDT files.
*
* @author Curtis Rueden ctrueden at wisc.edu
*/
public class SDTInfo {
// -- Constants --
public static final short BH_HEADER_CHKSUM = 0x55aa;
public static final short BH_HEADER_NOT_VALID = 0x1111;
public static final short BH_HEADER_VALID = 0x5555;
/** For .set files (setup only). */
public static final String SETUP_IDENTIFIER = "SPC Setup Script File";
/** For normal .sdt files (setup + data). */
public static final String DATA_IDENTIFIER = "SPC Setup & Data File";
/**
* For .sdt files created automatically in Continuous Flow mode measurement
* (no setup, only data).
*/
public static final String FLOW_DATA_IDENTIFIER = "SPC Flow Data File";
/**
* For .sdt files created using DLL function SPC_save_data_to_sdtfile
* (no setup, only data).
*/
public static final String DLL_DATA_IDENTIFIER = "SPC DLL Data File";
/**
* For .sdt files created in FIFO mode
* (setup, data blocks = Decay, FCS, FIDA, FILDA & MCS curves
* for each used routing channel).
*/
public static final String FCS_DATA_IDENTIFIER = "SPC FCS Data File";
public static final String X_STRING = "#SP [SP_SCAN_X,I,";
public static final String Y_STRING = "#SP [SP_SCAN_Y,I,";
public static final String T_STRING = "#SP [SP_ADC_RE,I,";
public static final String C_STRING = "#SP [SP_SCAN_RX,I,";
public static final String X_IMG_STRING = "#SP [SP_IMG_X,I,";
public static final String Y_IMG_STRING = "#SP [SP_IMG_Y,I,";
public static final String BINARY_SETUP = "BIN_PARA_BEGIN:\0";
// -- Fields --
public int width, height, timeBins, channels, timepoints;
// -- Fields - File header --
/** Software revision number (lower 4 bits >= 10(decimal)). */
public short revision;
/**
* Offset of the info part which contains general text
* information (Title, date, time, contents etc.).
*/
public int infoOffs;
/** Length of the info part. */
public short infoLength;
/**
* Offset of the setup text data
* (system parameters, display parameters, trace parameters etc.).
*/
public int setupOffs;
/** Length of the setup data. */
public short setupLength;
/** Offset of the first data block. */
public int dataBlockOffs;
/**
* no_of_data_blocks valid only when in 0 .. 0x7ffe range,
* if equal to 0x7fff the field 'reserved1' contains
* valid no_of_data_blocks.
*/
public short noOfDataBlocks;
// length of the longest block in the file
public int dataBlockLength;
// offset to 1st. measurement description block
// (system parameters connected to data blocks)
public int measDescBlockOffs;
// number of measurement description blocks
public short noOfMeasDescBlocks;
// length of the measurement description blocks
public short measDescBlockLength;
// valid: 0x5555, not valid: 0x1111
public int headerValid;
// reserved1 now contains noOfDataBlocks
public long reserved1; // unsigned
public int reserved2;
// checksum of file header
public int chksum;
// -- Fields - File Info --
public String info;
// -- Fields -- Setup --
public String setup;
// -- Fields - MeasureInfo --
public boolean hasMeasureInfo;
/** Time of creation. */
public String time;
/** Date of creation. */
public String date;
/** Serial number of the module. */
public String modSerNo;
public short measMode;
public float cfdLL;
public float cfdLH;
public float cfdZC;
public float cfdHF;
public float synZC;
public short synFD;
public float synHF;
public float tacR;
public short tacG;
public float tacOF;
public float tacLL;
public float tacLH;
public short adcRE;
public short ealDE;
public short ncx;
public short ncy;
public int page;
public float colT;
public float repT;
public short stopt;
public int overfl;
public short useMotor;
public int steps;
public float offset;
public short dither;
public short incr;
public short memBank;
/** Module type. */
public String modType;
public float synTH;
public short deadTimeComp;
/** 2 = disabled line markers. */
public short polarityL;
public short polarityF;
public short polarityP;
/** Line predivider = 2 ** (linediv). */
public short linediv;
public short accumulate;
public int flbckY;
public int flbckX;
public int bordU;
public int bordL;
public float pixTime;
public short pixClk;
public short trigger;
public int scanX;
public int scanY;
public int scanRX;
public int scanRY;
public short fifoTyp;
public int epxDiv;
public int modTypeCode;
/** New in v.8.4. */
public int modFpgaVer;
public float overflowCorrFactor;
public int adcZoom;
/** Cycles (accumulation cycles in FLOW mode). */
public int cycles;
// -- Fields - MeasStopInfo --
public boolean hasMeasStopInfo;
/** Last SPC_test_state return value (status). */
public int status;
/** Scan clocks bits 2-0 (frame, line, pixel), rates_read - bit 15. */
public int flags;
/**
* Time from start to - disarm (simple measurement)
* - or to the end of the cycle (for complex measurement).
*/
public float stopTime;
/** Current step (if multi-step measurement). */
public int curStep;
/**
* Current cycle (accumulation cycle in FLOW mode) -
* (if multi-cycle measurement).
*/
public int curCycle;
/** Current measured page. */
public int curPage;
/** Minimum rates during the measurement. */
public float minSyncRate;
/** (-1.0 - not set). */
public float minCfdRate;
public float minTacRate;
public float minAdcRate;
/** Maximum rates during the measurement. */
public float maxSyncRate;
/** (-1.0 - not set). */
public float maxCfdRate;
public float maxTacRate;
public float maxAdcRate;
public int mReserved1;
public float mReserved2;
// -- Fields - MeasFCSInfo --
public boolean hasMeasFCSInfo;
/** Routing channel number. */
public int chan;
/**
* Bit 0 = 1 - decay curve calculated.
* Bit 1 = 1 - fcs curve calculated.
* Bit 2 = 1 - FIDA curve calculated.
* Bit 3 = 1 - FILDA curve calculated.
* Bit 4 = 1 - MCS curve calculated.
* Bit 5 = 1 - 3D Image calculated.
*/
public int fcsDecayCalc;
/** Macro time clock in 0.1 ns units. */
public long mtResol; // unsigned
/** Correlation time [ms]. */
public float cortime;
/** No of photons. */
public long calcPhotons; // unsigned
/** No of FCS values. */
public int fcsPoints;
/** Macro time of the last photon. */
public float endTime;
/**
* No of Fifo overruns
* when > 0 fcs curve & endTime are not valid.
*/
public int overruns;
/**
* 0 - linear FCS with log binning (100 bins/log)
* when bit 15 = 1 (0x8000) - Multi-Tau FCS
* where bits 14-0 = ktau parameter.
*/
public int fcsType;
/**
* Cross FCS routing channel number
* when chan = crossChan and mod == crossMod - Auto FCS
* otherwise - Cross FCS.
*/
public int crossChan;
/** Module number. */
public int mod;
/** Cross FCS module number. */
public int crossMod;
/** Macro time clock of cross FCS module in 0.1 ns units. */
public long crossMtResol; // unsigned
// -- Fields - extended MeasureInfo -
public boolean hasExtendedMeasureInfo;
/**
* 4 subsequent fields valid only for Camera mode
* or FIFO_IMAGE mode.
*/
public int imageX;
public int imageY;
public int imageRX;
public int imageRY;
/** Gain for XY ADCs (SPC930). */
public short xyGain;
/** Use or not Master Clock (SPC140 multi-module). */
public short masterClock;
/** ADC sample delay (SPC-930). */
public short adcDE;
/** Detector type (SPC-930 in camera mode). */
public short detType;
/** X axis representation (SPC-930). */
public short xAxis;
// -- Fields - MeasHISTInfo --
public boolean hasMeasHISTInfo;
/** Interval time [ms] for FIDA histogram. */
public float fidaTime;
/** Interval time [ms] for FILDA histogram. */
public float fildaTime;
/** No of FIDA values. */
public int fidaPoints;
/** No of FILDA values. */
public int fildaPoints;
/** Interval time [ms] for MCS histogram. */
public float mcsTime;
/** No of MCS values. */
public int mcsPoints;
// -- Fields - extended binary header --
/** Number of MCS_TA points. */
public int mcstaPoints;
// -- Fields - BHFileBlockHeader --
/**
* Number of the block in the file.
* Valid only when in 0..0x7ffe range, otherwise use lblock_no field
* obsolete now, lblock_no contains full block no information.
*/
public short blockNo;
/** Offset of the data block from the beginning of the file. */
public int dataOffs;
/** Offset to the data block header of the next data block. */
public int nextBlockOffs;
public long[] allBlockOffsets;
public long[] allBlockLengths;
/** See blockType defines below. */
public int blockType;
/**
* Number of the measurement description block
* corresponding to this data block.
*/
public short measDescBlockNo;
/** Long blockNo - see remarks below. */
public long lblockNo; // unsigned
/** reserved2 now contains block (set) length. */
public long blockLength; // unsigned
// -- Constructor --
/**
* Constructs a new SDT header by reading values from the given input source,
* populating the given metadata table.
*/
public SDTInfo(RandomAccessInputStream in, Hashtable meta)
throws IOException
{
// read bhfileHeader
revision = in.readShort();
infoOffs = in.readInt();
infoLength = in.readShort();
setupOffs = in.readInt();
setupLength = in.readShort();
dataBlockOffs = in.readInt();
noOfDataBlocks = in.readShort();
dataBlockLength = in.readInt();
measDescBlockOffs = in.readInt();
noOfMeasDescBlocks = in.readShort();
measDescBlockLength = in.readShort();
headerValid = in.readUnsignedShort();
reserved1 = (0xffffffffL & in.readInt()); // unsigned
reserved2 = in.readUnsignedShort();
chksum = in.readUnsignedShort();
// save bhfileHeader to metadata table
if (meta != null) {
final String bhfileHeader = "bhfileHeader.";
meta.put(bhfileHeader + "revision", new Short(revision));
meta.put(bhfileHeader + "infoOffs", new Integer(infoOffs));
meta.put(bhfileHeader + "infoLength", new Short(infoLength));
meta.put(bhfileHeader + "setupOffs", new Integer(setupOffs));
meta.put(bhfileHeader + "dataBlockOffs", new Integer(dataBlockOffs));
meta.put(bhfileHeader + "noOfDataBlocks", new Short(noOfDataBlocks));
meta.put(bhfileHeader + "dataBlockLength",
new Integer(dataBlockLength));
meta.put(bhfileHeader + "measDescBlockOffs",
new Integer(measDescBlockOffs));
meta.put(bhfileHeader + "noOfMeasDescBlocks",
new Short(noOfMeasDescBlocks));
meta.put(bhfileHeader + "measDescBlockLength",
new Integer(measDescBlockLength));
meta.put(bhfileHeader + "headerValid", new Integer(headerValid));
meta.put(bhfileHeader + "reserved1", new Long(reserved1));
meta.put(bhfileHeader + "reserved2", new Integer(reserved2));
meta.put(bhfileHeader + "chksum", new Integer(chksum));
}
// read file info
in.seek(infoOffs);
byte[] infoBytes = new byte[infoLength];
in.readFully(infoBytes);
info = new String(infoBytes, Constants.ENCODING);
StringTokenizer st = new StringTokenizer(info, "\n");
int count = st.countTokens();
st.nextToken();
String key = null, value = null;
for (int i=1; i<count-1; i++) {
String token = st.nextToken().trim();
if (token.indexOf(":") == -1) continue;
key = token.substring(0, token.indexOf(":")).trim();
value = token.substring(token.indexOf(":") + 1).trim();
meta.put(key, value);
}
// read setup
in.seek(setupOffs);
byte[] setupBytes = new byte[setupLength];
in.readFully(setupBytes);
setup = new String(setupBytes, Constants.ENCODING);
int textEnd = setup.indexOf(BINARY_SETUP);
if (textEnd > 0) {
setup = setup.substring(0, textEnd);
textEnd += BINARY_SETUP.length();
in.seek(setupOffs + textEnd);
}
// variables to hold height & width read from header string for measMode 13
int mode13width = 0;
int mode13height = 0;
st = new StringTokenizer(setup, "\n");
while (st.hasMoreTokens()) {
String token = st.nextToken().trim();
if (token.startsWith("#SP") || token.startsWith("#DI") ||
token.startsWith("#PR") || token.startsWith("#MP"))
{
int open = token.indexOf("[");
key = token.substring(open + 1, token.indexOf(",", open));
value = token.substring(token.lastIndexOf(",") + 1, token.length() - 1);
}
else if (token.startsWith("#TR") || token.startsWith("#WI")) {
key = token.substring(0, token.indexOf("[")).trim();
value = token.substring(token.indexOf("[") + 1, token.indexOf("]"));
}
if (key != null && value != null) meta.put(key, value);
if (token.indexOf(X_STRING) != -1) {
int ndx = token.indexOf(X_STRING) + X_STRING.length();
int end = token.indexOf("]", ndx);
width = Integer.parseInt(token.substring(ndx, end));
}
else if (token.indexOf(Y_STRING) != -1) {
int ndx = token.indexOf(Y_STRING) + Y_STRING.length();
int end = token.indexOf("]", ndx);
height = Integer.parseInt(token.substring(ndx, end));
}
else if (token.indexOf(T_STRING) != -1) {
int ndx = token.indexOf(T_STRING) + T_STRING.length();
int end = token.indexOf("]", ndx);
timeBins = Integer.parseInt(token.substring(ndx, end));
}
else if (token.indexOf(C_STRING) != -1) {
int ndx = token.indexOf(C_STRING) + C_STRING.length();
int end = token.indexOf("]", ndx);
channels = Integer.parseInt(token.substring(ndx, end));
}
else if (token.indexOf(X_IMG_STRING) != -1) {
int ndx = token.indexOf(X_IMG_STRING) + X_IMG_STRING.length();
int end = token.indexOf("]", ndx);
mode13width = Integer.parseInt(token.substring(ndx, end));
}
else if (token.indexOf(Y_IMG_STRING) != -1) {
int ndx = token.indexOf(Y_IMG_STRING) + Y_IMG_STRING.length();
int end = token.indexOf("]", ndx);
mode13height = Integer.parseInt(token.substring(ndx, end));
}
}
if (in.getFilePointer() < setupOffs + setupLength) {
// BHBinHdr
in.skipBytes(4);
long baseOffset = in.getFilePointer();
long softwareRevision = readUnsignedLong(in);
long paramLength = readUnsignedLong(in);
long reserved1 = readUnsignedLong(in);
int reserved2 = in.readShort() & 0xffff;
// SPCBinHdr
long fcsOldOffset = readUnsignedLong(in);
long fcsOldSize = readUnsignedLong(in);
long gr1Offset = readUnsignedLong(in);
long gr1Size = readUnsignedLong(in);
long fcsOffset = readUnsignedLong(in);
long fcsSize = readUnsignedLong(in);
long fidaOffset = readUnsignedLong(in);
long fidaSize = readUnsignedLong(in);
long fildaOffset = readUnsignedLong(in);
long fildaSize = readUnsignedLong(in);
long gr2Offset = readUnsignedLong(in);
int grNo = in.readShort() & 0xffff;
int hstNo = in.readShort() & 0xffff;
long hstOffset = readUnsignedLong(in);
long gvdOffset = readUnsignedLong(in);
int gvdSize = in.readShort() & 0xffff;
int fitOffset = in.readShort() & 0xffff;
int fitSize = in.readShort() & 0xffff;
int extdevOffset = in.readShort() & 0xffff;
int extdevSize = in.readShort() & 0xffff;
long binhdrextOffset = readUnsignedLong(in);
int binhdrextSize = in.readShort() & 0xffff;
if (binhdrextOffset != 0) {
in.seek(baseOffset + binhdrextOffset);
long mcsImgOffset = readUnsignedLong(in);
long mcsImgSize = readUnsignedLong(in);
int momNo = in.readShort() & 0xffff;
int momSize = in.readShort() & 0xffff;
long momOffset = readUnsignedLong(in);
long sysparExtOffset = readUnsignedLong(in);
long sysparExtSize = readUnsignedLong(in);
long mosaicOffset = readUnsignedLong(in);
long mosaicSize = readUnsignedLong(in);
// 52 longs reserved
if (mcsImgOffset != 0) {
in.seek(baseOffset + mcsImgOffset);
int mcsActive = in.readInt();
in.skipBytes(4); // Window
mcstaPoints = in.readShort() & 0xffff;
int mcstaFlags = in.readShort() & 0xffff;
int mcstaTimePerPoint = in.readShort() & 0xffff;
float mcsOffset = in.readFloat();
float mcsTpp = in.readFloat();
if (meta != null) {
meta.put("MCS_TA.active", mcsActive);
meta.put("MCS_TA.points", mcstaPoints);
meta.put("MCS_TA.flags", mcstaFlags);
meta.put("MCS_TA.time per point", mcstaTimePerPoint);
}
}
}
}
// read measurement data
if (noOfMeasDescBlocks > 0) {
in.seek(measDescBlockOffs);
hasMeasureInfo = measDescBlockLength >= 211;
hasMeasStopInfo = measDescBlockLength >= 211 + 60;
hasMeasFCSInfo = measDescBlockLength >= 211 + 60 + 38;
hasExtendedMeasureInfo = measDescBlockLength >= 211 + 60 + 38 + 26;
hasMeasHISTInfo = measDescBlockLength >= 211 + 60 + 38 + 26 + 24;
if (hasMeasureInfo) {
time = in.readString(9).trim();
date = in.readString(11).trim();
modSerNo = in.readString(16).trim();
measMode = in.readShort();
cfdLL = in.readFloat();
cfdLH = in.readFloat();
cfdZC = in.readFloat();
cfdHF = in.readFloat();
synZC = in.readFloat();
synFD = in.readShort();
synHF = in.readFloat();
tacR = in.readFloat();
tacG = in.readShort();
tacOF = in.readFloat();
tacLL = in.readFloat();
tacLH = in.readFloat();
adcRE = in.readShort();
ealDE = in.readShort();
ncx = in.readShort();
ncy = in.readShort();
page = in.readUnsignedShort();
colT = in.readFloat();
repT = in.readFloat();
stopt = in.readShort();
overfl = in.readUnsignedByte();
useMotor = in.readShort();
steps = in.readUnsignedShort();
offset = in.readFloat();
dither = in.readShort();
incr = in.readShort();
memBank = in.readShort();
modType = in.readString(16).trim();
synTH = in.readFloat();
deadTimeComp = in.readShort();
polarityL = in.readShort();
polarityF = in.readShort();
polarityP = in.readShort();
linediv = in.readShort();
accumulate = in.readShort();
flbckY = in.readInt();
flbckX = in.readInt();
bordU = in.readInt();
bordL = in.readInt();
pixTime = in.readFloat();
pixClk = in.readShort();
trigger = in.readShort();
scanX = in.readInt();
scanY = in.readInt();
scanRX = in.readInt();
scanRY = in.readInt();
fifoTyp = in.readShort();
epxDiv = in.readInt();
modTypeCode = in.readUnsignedShort();
modFpgaVer = in.readUnsignedShort();
overflowCorrFactor = in.readFloat();
adcZoom = in.readInt();
cycles = in.readInt();
timepoints = stopt;
// save MeasureInfo to metadata table
if (meta != null) {
final String measureInfo = "MeasureInfo.";
meta.put(measureInfo + "time", time);
meta.put(measureInfo + "date", date);
meta.put(measureInfo + "modSerNo", modSerNo);
meta.put(measureInfo + "measMode", new Short(measMode));
meta.put(measureInfo + "cfdLL", new Float(cfdLL));
meta.put(measureInfo + "cfdLH", new Float(cfdLH));
meta.put(measureInfo + "cfdZC", new Float(cfdZC));
meta.put(measureInfo + "cfdHF", new Float(cfdHF));
meta.put(measureInfo + "synZC", new Float(synZC));
meta.put(measureInfo + "synFD", new Short(synFD));
meta.put(measureInfo + "synHF", new Float(synHF));
meta.put(measureInfo + "tacR", new Float(tacR));
meta.put(measureInfo + "tacG", new Short(tacG));
meta.put(measureInfo + "tacOF", new Float(tacOF));
meta.put(measureInfo + "tacLL", new Float(tacLL));
meta.put(measureInfo + "tacLH", new Float(tacLH));
meta.put(measureInfo + "adcRE", new Short(adcRE));
meta.put(measureInfo + "ealDE", new Short(ealDE));
meta.put(measureInfo + "ncx", new Short(ncx));
meta.put(measureInfo + "ncy", new Short(ncy));
meta.put(measureInfo + "page", new Integer(page));
meta.put(measureInfo + "colT", new Float(colT));
meta.put(measureInfo + "repT", new Float(repT));
meta.put(measureInfo + "stopt", new Short(stopt));
meta.put(measureInfo + "overfl", new Integer(overfl));
meta.put(measureInfo + "useMotor", new Short(useMotor));
meta.put(measureInfo + "steps", new Integer(steps));
meta.put(measureInfo + "offset", new Float(offset));
meta.put(measureInfo + "dither", new Short(dither));
meta.put(measureInfo + "incr", new Short(incr));
meta.put(measureInfo + "memBank", new Short(memBank));
meta.put(measureInfo + "modType", modType);
meta.put(measureInfo + "synTH", new Float(synTH));
meta.put(measureInfo + "deadTimeComp", new Short(deadTimeComp));
meta.put(measureInfo + "polarityL", new Short(polarityL));
meta.put(measureInfo + "polarityF", new Short(polarityF));
meta.put(measureInfo + "polarityP", new Short(polarityP));
meta.put(measureInfo + "linediv", new Short(linediv));
meta.put(measureInfo + "accumulate", new Short(accumulate));
meta.put(measureInfo + "flbckY", new Integer(flbckY));
meta.put(measureInfo + "flbckX", new Integer(flbckX));
meta.put(measureInfo + "bordU", new Integer(bordU));
meta.put(measureInfo + "bordL", new Integer(bordL));
meta.put(measureInfo + "pixTime", new Float(pixTime));
meta.put(measureInfo + "pixClk", new Short(pixClk));
meta.put(measureInfo + "trigger", new Short(trigger));
meta.put(measureInfo + "scanX", new Integer(scanX));
meta.put(measureInfo + "scanY", new Integer(scanY));
meta.put(measureInfo + "scanRX", new Integer(scanRX));
meta.put(measureInfo + "scanRY", new Integer(scanRY));
meta.put(measureInfo + "fifoTyp", new Short(fifoTyp));
meta.put(measureInfo + "epxDiv", new Integer(epxDiv));
meta.put(measureInfo + "modTypeCode", new Integer(modTypeCode));
meta.put(measureInfo + "modFpgaVer", new Integer(modFpgaVer));
meta.put(measureInfo + "overflowCorrFactor",
new Float(overflowCorrFactor));
meta.put(measureInfo + "adcZoom", new Integer(adcZoom));
meta.put(measureInfo + "cycles", new Integer(cycles));
}
// extract dimensional parameters from measure info
if (scanX > 0) width = scanX;
if (scanY > 0) height = scanY;
if (adcRE > 0) timeBins = adcRE;
if (scanRX > 0) channels = scanRX;
// measurement mode 0 and 1 are both single-point data
if (measMode == 0 || measMode == 1) {
width = 1;
height = 1;
}
// for measurement_mode 13 one channel is stored in each block
// & width & height are not in scanX & scanY
if (measMode == 13) {
width = mode13width;
height = mode13height;
channels = noOfMeasDescBlocks;
}
}
if (hasMeasStopInfo) {
// MeasStopInfo - information collected when measurement is finished
status = in.readUnsignedShort();
flags = in.readUnsignedShort();
stopTime = in.readFloat();
curStep = in.readInt();
curCycle = in.readInt();
curPage = in.readInt();
minSyncRate = in.readFloat();
minCfdRate = in.readFloat();
minTacRate = in.readFloat();
minAdcRate = in.readFloat();
maxSyncRate = in.readFloat();
maxCfdRate = in.readFloat();
maxTacRate = in.readFloat();
maxAdcRate = in.readFloat();
mReserved1 = in.readInt();
mReserved2 = in.readFloat();
// save MeasStopInfo to metadata table
if (meta != null) {
final String measStopInfo = "MeasStopInfo.";
meta.put(measStopInfo + "status", new Integer(status));
meta.put(measStopInfo + "flags", new Integer(flags));
meta.put(measStopInfo + "stopTime", new Float(stopTime));
meta.put(measStopInfo + "curStep", new Integer(curStep));
meta.put(measStopInfo + "curCycle", new Integer(curCycle));
meta.put(measStopInfo + "curPage", new Integer(curPage));
meta.put(measStopInfo + "minSyncRate", new Float(minSyncRate));
meta.put(measStopInfo + "minCfdRate", new Float(minCfdRate));
meta.put(measStopInfo + "minTacRate", new Float(minTacRate));
meta.put(measStopInfo + "minAdcRate", new Float(minAdcRate));
meta.put(measStopInfo + "maxSyncRate", new Float(maxSyncRate));
meta.put(measStopInfo + "maxCfdRate", new Float(maxCfdRate));
meta.put(measStopInfo + "maxTacRate", new Float(maxTacRate));
meta.put(measStopInfo + "maxAdcRate", new Float(maxAdcRate));
meta.put(measStopInfo + "reserved1", new Integer(mReserved1));
meta.put(measStopInfo + "reserved2", new Float(mReserved2));
}
}
if (hasMeasFCSInfo) {
// MeasFCSInfo - information collected when FIFO measurement is finished
chan = in.readUnsignedShort();
fcsDecayCalc = in.readUnsignedShort();
mtResol = (0xffffffffL & in.readInt()); // unsigned
cortime = in.readFloat();
calcPhotons = (0xffffffffL & in.readInt()); // unsigned
fcsPoints = in.readInt();
endTime = in.readFloat();
overruns = in.readUnsignedShort();
fcsType = in.readUnsignedShort();
crossChan = in.readUnsignedShort();
mod = in.readUnsignedShort();
crossMod = in.readUnsignedShort();
crossMtResol = (0xffffffffL & in.readInt()); // unsigned
// save MeasFCSInfo to metadata table
if (meta != null) {
final String measFCSInfo = "MeasFCSInfo.";
meta.put(measFCSInfo + "chan", new Integer(chan));
meta.put(measFCSInfo + "fcsDecayCalc", new Integer(fcsDecayCalc));
meta.put(measFCSInfo + "mtResol", new Long(mtResol));
meta.put(measFCSInfo + "cortime", new Float(cortime));
meta.put(measFCSInfo + "calcPhotons", new Long(calcPhotons));
meta.put(measFCSInfo + "fcsPoints", new Integer(fcsPoints));
meta.put(measFCSInfo + "endTime", new Float(endTime));
meta.put(measFCSInfo + "overruns", new Integer(overruns));
meta.put(measFCSInfo + "fcsType", new Integer(fcsType));
meta.put(measFCSInfo + "crossChan", new Integer(crossChan));
meta.put(measFCSInfo + "mod", new Integer(mod));
meta.put(measFCSInfo + "crossMod", new Integer(crossMod));
meta.put(measFCSInfo + "crossMtResol", new Float(crossMtResol));
}
}
if (hasExtendedMeasureInfo) {
imageX = in.readInt();
imageY = in.readInt();
imageRX = in.readInt();
imageRY = in.readInt();
xyGain = in.readShort();
masterClock = in.readShort();
adcDE = in.readShort();
detType = in.readShort();
xAxis = in.readShort();
// save extra MeasureInfo to metadata table
if (meta != null) {
final String measureInfo = "MeasureInfo.";
meta.put(measureInfo + "imageX", new Integer(imageX));
meta.put(measureInfo + "imageY", new Integer(imageY));
meta.put(measureInfo + "imageRX", new Integer(imageRX));
meta.put(measureInfo + "imageRY", new Integer(imageRY));
meta.put(measureInfo + "xyGain", new Short(xyGain));
meta.put(measureInfo + "masterClock", new Short(masterClock));
meta.put(measureInfo + "adcDE", new Short(adcDE));
meta.put(measureInfo + "detType", new Short(detType));
meta.put(measureInfo + "xAxis", new Short(xAxis));
}
}
if (hasMeasHISTInfo) {
// MeasHISTInfo - extension of FCSInfo, valid only for FIFO meas
// extension of MeasFCSInfo for other histograms (FIDA, FILDA, MCS)
fidaTime = in.readFloat();
fildaTime = in.readFloat();
fidaPoints = in.readInt();
fildaPoints = in.readInt();
mcsTime = in.readFloat();
mcsPoints = in.readInt();
// save MeasHISTInfo to metadata table
if (meta != null) {
final String measHISTInfo = "MeasHISTInfo.";
meta.put(measHISTInfo + "fidaTime", new Float(fidaTime));
meta.put(measHISTInfo + "fildaTime", new Float(fildaTime));
meta.put(measHISTInfo + "fidaPoints", new Integer(fidaPoints));
meta.put(measHISTInfo + "fildaPoints", new Integer(fildaPoints));
meta.put(measHISTInfo + "mcsTime", new Float(mcsTime));
meta.put(measHISTInfo + "mcsPoints", new Integer(mcsPoints));
}
}
}
in.seek(dataBlockOffs);
allBlockOffsets = new long[noOfDataBlocks];
allBlockLengths = new long[noOfDataBlocks];
for (int i=0; i<noOfDataBlocks; i++) {
// read BHFileBlockHeader
blockNo = in.readShort();
dataOffs = in.readInt();
nextBlockOffs = in.readInt();
blockType = in.readUnsignedShort();
measDescBlockNo = in.readShort();
lblockNo = (0xffffffffL & in.readInt()); // unsigned
int len = in.readInt();
blockLength = (0xffffffffL & len); // unsigned
allBlockOffsets[i] = in.getFilePointer();
allBlockLengths[i] = blockLength;
// save BHFileBlockHeader to metadata table
if (meta != null) {
final String bhFileBlockHeader = "BHFileBlockHeader.";
meta.put(bhFileBlockHeader + "blockNo", new Short(blockNo));
meta.put(bhFileBlockHeader + "dataOffs", new Integer(dataOffs));
meta.put(bhFileBlockHeader + "nextBlockOffs",
new Integer(nextBlockOffs));
meta.put(bhFileBlockHeader + "blockType", new Integer(blockType));
meta.put(bhFileBlockHeader + "measDescBlockNo",
new Short(measDescBlockNo));
meta.put(bhFileBlockHeader + "lblockNo", new Long(lblockNo));
meta.put(bhFileBlockHeader + "blockLength", new Long(blockLength));
}
in.skipBytes(len);
}
}
private long readUnsignedLong(RandomAccessInputStream in) throws IOException {
return in.readInt() & 0xffffffffL;
}
}