Brief description of class still missing. More...
#include <SEGYTraceHeader.h>
Brief description of class still missing.
Format of SEGY trace header (same as the SU trace header) The following offsets are read from SEG Y rev 1 (2002) SEG Technical Standards Committee
This document is available at: http://www.seg.org/SEGportalWEBproject/prod/SEG-Publications/Pub-Technical-Standards/Documents/seg_y_rev1.pdf
References TRACE.
{ TRACE; ASSERT(sizeof(SEGYTraceHeader)==240); memset(this, 0, 240); }
QDateTime GeopsyCore::SEGYTraceHeader::dateTime | ( | ) | const |
SignalFileFormat::Format GeopsyCore::SEGYTraceHeader::determineByteOrderSEGY | ( | QString | fileName | ) | [static] |
Determination of byter order is based on sample type read from file header. For SEGY format only.
References QGpCoreTools::endl(), isSampleCodingValid(), GeopsyCore::SignalFileFormat::SegYBigEndian, GeopsyCore::SignalFileFormat::SegYLittleEndian, QGpCoreTools::tr(), TRACE, and GeopsyCore::SignalFileFormat::Unknown.
Referenced by GeopsyCore::SignalFileFormat::fromContent(), and GeopsyCore::SignalFileFormat::fromSuffix().
{ TRACE; QFile f(fileName); if( !f.open(QIODevice::ReadOnly) ) { return SignalFileFormat::Unknown; } QDataStream s(&f); qint64 binHeaderOffset=3200; // Skip file header: need the number of extended textual file headers and sample coding qint16 sampleCoding; s.setByteOrder(QDataStream::LittleEndian); f.seek(binHeaderOffset + 24); s >> sampleCoding; bool littleEndian=isSampleCodingValid(sampleCoding); s.setByteOrder(QDataStream::BigEndian); f.seek(binHeaderOffset + 24); s >> sampleCoding; bool bigEndian=isSampleCodingValid(sampleCoding); if((littleEndian && bigEndian) || (!littleEndian && !bigEndian)) { App::stream() << tr("Cannot determine byte order for SEGY format.") << endl; return SignalFileFormat::Unknown; } else if(littleEndian) { return SignalFileFormat::SegYLittleEndian; } else { return SignalFileFormat::SegYBigEndian; } }
SignalFileFormat::Format GeopsyCore::SEGYTraceHeader::determineByteOrderSU | ( | QString | fileName | ) | [static] |
Determination of byter order is based on number of samples read from trace header. There is no other fixed and mandatory field that can help us to determine the byte order. All traces are read and number of samples are calculated, if it matched the file size, than there are good chances that the right byte order has been found. For SU format only.
References QGpCoreTools::endl(), GeopsyCore::SignalFileFormat::SuBigEndian, GeopsyCore::SignalFileFormat::SuLittleEndian, QGpCoreTools::tr(), TRACE, and GeopsyCore::SignalFileFormat::Unknown.
Referenced by GeopsyCore::SignalFileFormat::fromContent(), and GeopsyCore::SignalFileFormat::fromSuffix().
{ TRACE; QFile f(fileName); if( !f.open(QIODevice::ReadOnly) ) { return SignalFileFormat::Unknown; } QDataStream s(&f); s.setByteOrder(QDataStream::LittleEndian); bool littleEndian=suCanReadAll(s, f.size()); f.seek(0); s.setByteOrder(QDataStream::BigEndian); bool bigEndian=suCanReadAll(s, f.size()); if((littleEndian && bigEndian) || (!littleEndian && !bigEndian)) { App::stream() << tr("Cannot determine byte order for SU format.") << endl; return SignalFileFormat::Unknown; } else if(littleEndian) { return SignalFileFormat::SuLittleEndian; } else { return SignalFileFormat::SuBigEndian; } }
double GeopsyCore::SEGYTraceHeader::IBMFloat2ieee | ( | qint32 | val | ) | [static] |
Conversion from IBM floats to IEEE double precision.
See http://en.wikipedia.org/wiki/IBM_Floating_Point_Architecture for IBM structure.
References QGpCoreTools::exp(), and TRACE.
{ TRACE; //val=0xC276A000; // test: -118.625 with IBM floats (see wiki) /* 2^(-24)*16^(t-64)=2^(-24)*2^(4t-256)=2^(4t-280) -24 is to set fmant as a fraction -256 for ibm float bias +1023 to introduce double bias (-280+1023)*16=0x2E70 16 is a 4-bit shift, from short to 12 bit representation of double exp 0x7f00 & *(reinterpret_cast<unsigned short *>(&val)+1) is the ibm float exp multiplied by 16 which must be multipled by 4, hence only divided by 4. Conversion to IEEE double: For a null fraction, val=2^(exp-1023), 2^-1=3fe0 0000 0000 0000 (3fe=1022) 2^-2=3fd0 0000 0000 0000 */ double res=0.0; if(val) { union { double val; unsigned short s[4]; } t; t.val=0.0; double fmant=static_cast<double>(0x00ffffff & val); #if Q_BYTE_ORDER==Q_BIG_ENDIAN // Never tested on a big endian architecture unsigned short& exp=t.s[0]; #else unsigned short& exp=t.s[3]; #endif exp=(0x7f000000 & val) >> 18; exp+=0x2E70; if(val<0) { // negative number res=-fmant*t.val; } else { res=fmant*t.val; } } return res; }
bool GeopsyCore::SEGYTraceHeader::isSampleCodingValid | ( | qint16 | sampleCoding | ) | [static] |
Referenced by determineByteOrderSEGY().
{ switch(sampleCoding) { case 1: case 2: case 3: case 5: case 8: return true; default: return false; } }
void GeopsyCore::SEGYTraceHeader::read | ( | QDataStream & | s | ) |
{ TRACE; for(int i=0;i<7;i++) s >> raw.raw0[i]; for(int i=0;i<4;i++) s >> raw.raw1[i]; for(int i=0;i<8;i++) s >> raw.raw2[i]; for(int i=0;i<2;i++) s >> raw.raw3[i]; for(int i=0;i<4;i++) s >> raw.raw4[i]; for(int i=0;i<46;i++) s >> raw.raw5[i]; for(int i=0;i<5;i++) s >> raw.raw6[i]; for(int i=0;i<20;i++) s >> raw.raw7[i]; }
Point GeopsyCore::SEGYTraceHeader::receiver | ( | ) | const |
bool GeopsyCore::SEGYTraceHeader::setCoordinateFactor | ( | const Point & | rec, |
const Point & | src | ||
) |
References QGpCoreTools::endl(), field, QGpCoreTools::tr(), QGpCoreTools::Point2D::x(), and QGpCoreTools::Point2D::y().
Referenced by GeopsyCore::Signal::writeSegySu().
{ double max=fabs(src.x()); double min=fabs(src.x()); if(fabs(src.y())>max) max=fabs(src.y()); else if(fabs(src.y())<min) min=fabs(src.y()); if(fabs(rec.x())>max) max=fabs(rec.x()); else if(fabs(rec.x())<min) min=fabs(rec.x()); if(fabs(rec.y())>max) max=fabs(rec.y()); else if(fabs(rec.y())<min) min=fabs(rec.y()); field.coordinateFactor=factor(min, max, 2147483647.0); if(field.coordinateFactor==0) { App::stream() << tr("Coordinate range cannot be represented with SEGY format ([%1, %2]).").arg(min).arg(max) << endl; return false; } else { return true; } }
bool GeopsyCore::SEGYTraceHeader::setElevationFactor | ( | const Point & | rec, |
const Point & | src | ||
) |
References field, and QGpCoreTools::Point::z().
Referenced by GeopsyCore::Signal::writeSegySu().
bool GeopsyCore::SEGYTraceHeader::setNSamples | ( | int | n | ) |
References QGpCoreTools::endl(), field, QGpCoreTools::tr(), and TRACE.
Referenced by GeopsyCore::Signal::writeSegySu().
void GeopsyCore::SEGYTraceHeader::setReceiver | ( | const Point & | rec | ) |
References field, QGpCoreTools::Point2D::x(), QGpCoreTools::Point2D::y(), and QGpCoreTools::Point::z().
Referenced by GeopsyCore::Signal::writeSegySu().
{ double sfxy=encodeCoordinateFactor(); double sfz=encodeElevationFactor(); field.receiverXCoordinate=(qint32)round(rec.x()*sfxy); field.receiverYCoordinate=(qint32)round(rec.y()*sfxy); field.receiverElevation=(qint32)round(rec.z()*sfz); field.receiverDatumElevation=0; field.coordinateUnit=1; // Length (Meters or feet) }
void GeopsyCore::SEGYTraceHeader::setSource | ( | const Point & | src | ) |
References field, QGpCoreTools::Point2D::x(), QGpCoreTools::Point2D::y(), and QGpCoreTools::Point::z().
Referenced by GeopsyCore::Signal::writeSegySu().
{ double sfxy=encodeCoordinateFactor(); double sfz=encodeElevationFactor(); field.sourceXCoordinate=(qint32)round(src.x()*sfxy); field.sourceYCoordinate=(qint32)round(src.y()*sfxy); field.sourceSurfaceElevation=(qint32)round(src.z()*sfz); field.sourceDepth=0; field.sourceDatumElevation=0; field.coordinateUnit=1; // Length (Meters or feet) }
bool GeopsyCore::SEGYTraceHeader::setSUT0 | ( | double | t | ) |
SU considers all fields after byte 180 differently than SEGY standard.
References QGpCoreTools::endl(), field, QGpCoreTools::tr(), and TRACE.
Referenced by GeopsyCore::Signal::writeSegySu().
bool GeopsyCore::SEGYTraceHeader::setT0 | ( | double | t | ) |
T0 according to SEGY standard.
References QGpCoreTools::endl(), field, QGpCoreTools::tr(), and TRACE.
Referenced by GeopsyCore::Signal::writeSegySu().
{ TRACE; t*=1e3; // milliseconds is stored field.timeFactor=factor(t, t, 32767.0); if(field.timeFactor==0) { App::stream() << tr("T0 cannot be represented with SEGY format (%1 ms).").arg(t) << endl; return false; } else { double f=encodeTimeFactor(); field.delayRecordingTime=(int)round(f*t); return true; } }
Point GeopsyCore::SEGYTraceHeader::source | ( | ) | const |
double GeopsyCore::SEGYTraceHeader::SUt0 | ( | ) | const |
double GeopsyCore::SEGYTraceHeader::t0 | ( | ) | const |
void GeopsyCore::SEGYTraceHeader::write | ( | QDataStream & | s | ) |
Referenced by GeopsyCore::Signal::writeSegySu().
{ TRACE; for(int i=0;i<7;i++) s << raw.raw0[i]; for(int i=0;i<4;i++) s << raw.raw1[i]; for(int i=0;i<8;i++) s << raw.raw2[i]; for(int i=0;i<2;i++) s << raw.raw3[i]; for(int i=0;i<4;i++) s << raw.raw4[i]; for(int i=0;i<46;i++) s << raw.raw5[i]; for(int i=0;i<5;i++) s << raw.raw6[i]; for(int i=0;i<20;i++) s << raw.raw7[i]; }
union { ... } |
struct { ... } GeopsyCore::SEGYTraceHeader::field |
Referenced by dateTime(), receiver(), setCoordinateFactor(), setElevationFactor(), setNSamples(), setReceiver(), setSource(), setSUT0(), setT0(), source(), SUt0(), t0(), and GeopsyCore::Signal::writeSegySu().
struct { ... } GeopsyCore::SEGYTraceHeader::raw |
qint32 GeopsyCore::SEGYTraceHeader::raw0[7] |
qint16 GeopsyCore::SEGYTraceHeader::raw1[4] |
qint32 GeopsyCore::SEGYTraceHeader::raw2[8] |
qint16 GeopsyCore::SEGYTraceHeader::raw3[2] |
qint32 GeopsyCore::SEGYTraceHeader::raw4[4] |
qint16 GeopsyCore::SEGYTraceHeader::raw5[46] |
qint32 GeopsyCore::SEGYTraceHeader::raw6[5] |
qint16 GeopsyCore::SEGYTraceHeader::raw7[20] |