package edu.sc.seis.seisFile.segd;
import org.apache.log4j.Logger;
import java.io.BufferedInputStream;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import com.isti.traceview.common.TimeInterval;
public class Trace {
private static final Logger logger = Logger.getLogger(Trace.class);
public enum TraceEdit {
NO_EDIT,
DEAD_CHANNEL,
INTENTIONALLY_ZEROED,
EDITED
};
public enum SensorType {
NOT_DEFINED,
PRESSURE,
VELOCITY_VERTICAL,
VELOCITY_HORIZONTAL_INLINE,
VELOCITY_HORIZONTAL_CROSSLINE,
VELOCITY_HORIZONTAL_OTHER,
ACCELERATION_VERTICAL,
ACCELERATION_HORIZONTAL_INLINE,
ACCELERATION_HORIZONTAL_CROSSLINE,
ACCELERATION_HORIZONTAL_OTHER
};
private SegdRecord record = null;
private int fileNumber = -1;
private int scanTypeNumber = -1;
private int channelSetNumber = -1;
private int traceNumber = -1;
private double timingWord = 0.0;
private short traceHeaderExtensions_number = -1;
private double sampleSkew_fraction = 0.0;
private TraceEdit traceEdit = null;
private double timeBreakWindow = 0.0;
//-------1st ext header data----------
private double receiverLineNumber = 0.0;
private double receiverPointNumber = 0.0;
private byte receiverPointIndex = -1;
private int samplesNumber = -1;
private SensorType sensorType = null;
private long dataOffset = -1;
//------------------------------------
private float[] data = null;
private float minDataValue;
private float maxDataValue;
public Trace(SegdRecord parent){
this.record = parent;
minDataValue = Float.MAX_VALUE;
maxDataValue = Float.MIN_VALUE;
}
public int getFileNumber() {
return fileNumber;
}
public int getScanTypeNumber() {
return scanTypeNumber;
}
public int getChannelSetNumber() {
return channelSetNumber;
}
public int getTraceNumber() {
return traceNumber;
}
public double getTimingWord() {
return timingWord;
}
public short getTraceHeaderExtensions_number() {
return traceHeaderExtensions_number;
}
public double getSampleSkew_fraction() {
return sampleSkew_fraction;
}
public TraceEdit getTraceEdit() {
return traceEdit;
}
public double getTimeBreakWindow() {
return timeBreakWindow;
}
public double getReceiverLineNumber() {
return receiverLineNumber;
}
public double getReceiverPointNumber() {
return receiverPointNumber;
}
public byte getReceiverPointIndex() {
return receiverPointIndex;
}
public int getSamplesNumber() {
return samplesNumber;
}
public SensorType getSensorType() {
return sensorType;
}
public float[] getData() {
return data;
}
public float getMinDataValue() {
return minDataValue;
}
public float getMaxDataValue() {
return maxDataValue;
}
public long getDataOffset(){
return dataOffset;
}
public void setDataOffset(long offset){
this.dataOffset = offset;
}
public TimeInterval getTimeRange(){
long startTime = record.getDate().getTime() + new Double(timingWord).longValue();
return new TimeInterval(startTime, startTime + new Double(samplesNumber*record.getBaseScanInterval()).longValue());
}
public void readHeader(DataInput inStream) throws IOException{
try {
short[] check = { 0xFF, 0xFF };
fileNumber = SegdRecord.getDataValue(SegdRecord.getSections(SegdRecord.readBytes(inStream, 2, check), 4), 10);
} catch (CheckFailedException e) {
// Does nothing
logger.error("CheckFailedException:", e);
} catch (SegdException e) {
logger.error("SegdException:", e);
}
try {
short[] check = { 0xFF };
scanTypeNumber = SegdRecord.getDataValue(SegdRecord.getSections(SegdRecord.readBytes(inStream, 1, check), 4), 10);
} catch (CheckFailedException e) {
// Does nothing
logger.error("CheckFailedException:", e);
} catch (SegdException e) {
logger.error("SegdException:", e);
}
try {
short[] check = { 0xFF };
channelSetNumber = SegdRecord.getDataValue(SegdRecord.getSections(SegdRecord.readBytes(inStream, 1, check), 4), 10);
} catch (CheckFailedException e) {
// Does nothing
logger.error("CheckFailedException:", e);
} catch (SegdException e) {
logger.error("SegdException:", e);
}
try {
traceNumber = SegdRecord.getDataValue(SegdRecord.getSections(SegdRecord.readBytes(inStream, 2, null), 4), 10);
} catch (CheckFailedException e) {
logger.error("CheckFailedException:", e);
} catch (SegdException e) {
logger.error("SegdException:", e);
}
try {
int timeWordInteger = SegdRecord.readShorts(inStream, 1)[0];
short timeWordFraction = SegdRecord.readBytes(inStream, 1, null)[0];
timingWord = timeWordInteger + timeWordFraction/256.0;
} catch (CheckFailedException e) {
logger.error("CheckFailedException:", e);
} catch (SegdException e) {
logger.error("SegdException:", e);
}
try {
traceHeaderExtensions_number = SegdRecord.readBytes(inStream, 1, null)[0];
} catch (CheckFailedException e) {
logger.error("CheckFailedException:", e);
} catch (SegdException e) {
logger.error("SegdException:", e);
}
try {
sampleSkew_fraction = SegdRecord.readBytes(inStream, 1, null)[0]/256;
} catch (CheckFailedException e) {
logger.error("CheckFailedException:", e);
} catch (SegdException e) {
logger.error("SegdException:", e);
}
try {
short byte12 = SegdRecord.readBytes(inStream, 1, null)[0];
switch (byte12) {
case 0:
traceEdit = TraceEdit.NO_EDIT;
break;
case 1:
traceEdit = TraceEdit.DEAD_CHANNEL;
break;
case 2:
traceEdit = TraceEdit.INTENTIONALLY_ZEROED;
break;
case 3:
traceEdit = TraceEdit.EDITED;
break;
default:
traceEdit = null;
}
} catch (CheckFailedException e) {
logger.error("CheckFailedException:", e);
} catch (SegdException e) {
logger.error("SegdException:", e);
}
try {
int timeBreakInteger = SegdRecord.readShorts(inStream, 1)[0];
short timeBreakFraction = SegdRecord.readBytes(inStream, 1, null)[0];
timeBreakWindow = timeBreakInteger + timeBreakFraction/256.0;
} catch (CheckFailedException e) {
logger.error("CheckFailedException:", e);
} catch (SegdException e) {
logger.error("SigdException:", e);
}
//if(channelSetNumber == -1){
channelSetNumber = SegdRecord.readShorts(inStream, 1)[0];
//} else {
// inStream.skipBytes(2);
//}
if(fileNumber == -1){
fileNumber = SegdRecord.readUnsignedTriple(inStream);
} else {
inStream.skipBytes(3);
}
readExtHeaders(inStream);
}
private void readExtHeaders(DataInput inStream) throws IOException {
if(traceHeaderExtensions_number>0){
int receiverLineNumberInt = SegdRecord.readSignedTriple(inStream);
int receiverPointNumberInt = SegdRecord.readSignedTriple(inStream);
receiverPointIndex = inStream.readByte();
samplesNumber = SegdRecord.readUnsignedTriple(inStream);
if (receiverLineNumberInt == 0xFFFFFF) {
receiverLineNumber = readSignedFractionedFive(inStream);
} else {
receiverLineNumber = receiverLineNumberInt;
inStream.skipBytes(5);
}
if (receiverPointNumberInt == 0xFFFFFF) {
receiverPointNumber = readSignedFractionedFive(inStream);
} else {
receiverPointNumber = receiverPointNumberInt;
inStream.skipBytes(5);
}
try {
short byte21 = SegdRecord.readBytes(inStream, 1, null)[0];
switch (byte21) {
case 0:
sensorType = SensorType.NOT_DEFINED;
break;
case 1:
sensorType = SensorType.PRESSURE;
break;
case 2:
sensorType = SensorType.VELOCITY_VERTICAL;
break;
case 3:
sensorType = SensorType.VELOCITY_HORIZONTAL_INLINE;
break;
case 4:
sensorType = SensorType.VELOCITY_HORIZONTAL_CROSSLINE;
break;
case 5:
sensorType = SensorType.VELOCITY_HORIZONTAL_OTHER;
break;
case 6:
sensorType = SensorType.ACCELERATION_VERTICAL;
break;
case 7:
sensorType = SensorType.ACCELERATION_HORIZONTAL_INLINE;
break;
case 8:
sensorType = SensorType.ACCELERATION_HORIZONTAL_CROSSLINE;
break;
case 9:
sensorType = SensorType.ACCELERATION_HORIZONTAL_OTHER;
break;
default:
sensorType= null;
}
} catch (CheckFailedException e) {
logger.error("CheckFailedException:", e);
} catch (SegdException e) {
logger.error("SegdException:", e);
}
inStream.skipBytes(11);//not used
}
//Skip all subsequent ext headers
inStream.skipBytes(32*(traceHeaderExtensions_number-1));
}
public void readData(DataInput inStream)throws IOException{
if(data == null) {
data = new float[samplesNumber];
}
for(int i = 0; i<samplesNumber; i++){
float val = inStream.readFloat();
data[i] = val;
if(val>maxDataValue){
maxDataValue = val;
}
if(val<minDataValue){
minDataValue = val;
}
}
}
public static float[] getData(File file, long offset, int samplesCount) throws IOException{
float[] ret = new float[samplesCount];
DataInputStream strm = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
strm.skipBytes((int)offset);
//BufferedRandomAccessFile strm = new BufferedRandomAccessFile(file.getCanonicalPath(), "r");
//strm.seek(offset);
for(int i = 0; i<samplesCount; i++){
ret[i] = strm.readFloat();
}
strm.close();
return ret;
}
static double readSignedFractionedFive(DataInput inStream) throws IOException {
int intPart = SegdRecord.readSignedTriple(inStream);
double fractionPart = SegdRecord.readShorts(inStream, 1)[0] / 65536.0;
return intPart + fractionPart;
}
public String toString(){
return "\n\t\tTrace # " + traceNumber
+"\n\t\t\tFile number: " + fileNumber
+"\n\t\t\tScan Type number: " + scanTypeNumber
+"\n\t\t\tChannel Set number: " + channelSetNumber
+"\n\t\t\tTiming word, ms: " + timingWord
+"\n\t\t\tTrace Header Extensions number: " + traceHeaderExtensions_number
+"\n\t\t\tSample Skew (fraction part): " + sampleSkew_fraction
+"\n\t\t\tTrace edit status: " + traceEdit
+"\n\t\t\tTime break window, ms: " + timeBreakWindow
+ "\n\t\t\tReceiver Line number: " + receiverLineNumber
+ "\n\t\t\tReceiver Point number: " + receiverPointNumber
+ "\n\t\t\tReceiver Point index: " + receiverPointIndex
+ "\n\t\t\tSamples number: " + samplesNumber
+ "\n\t\t\tSensor type: " + sensorType
+ "\n\t\t\tData offset: " + dataOffset;
}
}