Task 854: .Y File Format
Task 854: .Y File Format
1. Properties of the .Y File Format Intrinsic to Its File System
(No changes required, as this section is already comprehensive.)
2. Two Direct Download Links for Files of Format .Y
(No changes required.)
3. Ghost Blog Embedded HTML JavaScript for Drag-and-Drop .Y File Dump
The JavaScript in the HTML snippet has been upgraded to parse and display all binary file header fields explicitly, based on the SEG-Y revision 1 specification. The parsing now includes extraction and output for every defined field in the 400-byte binary header.
4. Python Class for Handling .Y Files
The Python class has been upgraded to fully unpack and pack all binary file header fields using struct. The binary_header dictionary now includes every specified field, and the write method packs all fields accordingly. Unassigned bytes are handled with padding.
import struct
import os
class SegYHandler:
def __init__(self, filepath):
self.filepath = filepath
self.textual_header = None
self.binary_header = {}
self.trace_headers = []
self.data = [] # Simplified; stores first trace data as example
def read(self):
with open(self.filepath, 'rb') as f:
# Read Textual Header
self.textual_header = f.read(3200).decode('cp037') # EBCDIC
# Read Binary Header (full unpack)
binary_data = f.read(400)
self.binary_header = {
'job_id': struct.unpack('>i', binary_data[0:4])[0],
'line_num': struct.unpack('>i', binary_data[4:8])[0],
'reel_num': struct.unpack('>i', binary_data[8:12])[0],
'data_traces_ensemble': struct.unpack('>h', binary_data[12:14])[0],
'aux_traces_ensemble': struct.unpack('>h', binary_data[14:16])[0],
'sample_interval': struct.unpack('>h', binary_data[16:18])[0],
'orig_sample_interval': struct.unpack('>h', binary_data[18:20])[0],
'samples_per_trace': struct.unpack('>h', binary_data[20:22])[0],
'orig_samples_per_trace': struct.unpack('>h', binary_data[22:24])[0],
'format_code': struct.unpack('>h', binary_data[24:26])[0],
'ensemble_fold': struct.unpack('>h', binary_data[26:28])[0],
'trace_sorting': struct.unpack('>h', binary_data[28:30])[0],
'vertical_sum': struct.unpack('>h', binary_data[30:32])[0],
'sweep_freq_start': struct.unpack('>h', binary_data[32:34])[0],
'sweep_freq_end': struct.unpack('>h', binary_data[34:36])[0],
'sweep_length': struct.unpack('>h', binary_data[36:38])[0],
'sweep_type': struct.unpack('>h', binary_data[38:40])[0],
'sweep_channel': struct.unpack('>h', binary_data[40:42])[0],
'sweep_taper_start': struct.unpack('>h', binary_data[42:44])[0],
'sweep_taper_end': struct.unpack('>h', binary_data[44:46])[0],
'taper_type': struct.unpack('>h', binary_data[46:48])[0],
'correlated_traces': struct.unpack('>h', binary_data[48:50])[0],
'binary_gain': struct.unpack('>h', binary_data[50:52])[0],
'amp_recovery': struct.unpack('>h', binary_data[52:54])[0],
'measurement_system': struct.unpack('>h', binary_data[54:56])[0],
'impulse_polarity': struct.unpack('>h', binary_data[56:58])[0],
'vibratory_polarity': struct.unpack('>h', binary_data[58:60])[0],
# Unassigned: 60-260 (bytes 3261-3500 relative to file start)
'segy_revision': struct.unpack('>H', binary_data[300:302])[0], # Unsigned
'fixed_trace_flag': struct.unpack('>h', binary_data[302:304])[0],
'ext_text_headers': struct.unpack('>h', binary_data[304:306])[0],
# Unassigned: 306-400 (bytes 3507-3600)
}
# Read First Trace Header (example; extend for all traces)
trace_header_data = f.read(240)
trace_header = {
'trace_seq_line': struct.unpack('>i', trace_header_data[0:4])[0],
# ... (Trace fields remain partial)
}
self.trace_headers.append(trace_header)
# Read Data (simplified)
num_samples = self.binary_header['samples_per_trace']
format_code = self.binary_header['format_code']
if format_code == 5: # IEEE float
trace_data = struct.unpack('>' + 'f' * num_samples, f.read(4 * num_samples))
self.data.append(trace_data)
def print_properties(self):
print("Textual Header:")
print(self.textual_header)
print("\nBinary Header:")
for key, value in self.binary_header.items():
print(f"{key}: {value}")
print("\nTrace Headers:")
for th in self.trace_headers:
for key, value in th.items():
print(f"{key}: {value}")
def write(self, output_path):
with open(output_path, 'wb') as f:
f.write(self.textual_header.encode('cp037'))
# Full pack for binary header
binary_packed = struct.pack('>iii hhhhhhhhhhhhhhhhhhhhhhhh H h h',
self.binary_header['job_id'],
self.binary_header['line_num'],
self.binary_header['reel_num'],
self.binary_header['data_traces_ensemble'],
self.binary_header['aux_traces_ensemble'],
self.binary_header['sample_interval'],
self.binary_header['orig_sample_interval'],
self.binary_header['samples_per_trace'],
self.binary_header['orig_samples_per_trace'],
self.binary_header['format_code'],
self.binary_header['ensemble_fold'],
self.binary_header['trace_sorting'],
self.binary_header['vertical_sum'],
self.binary_header['sweep_freq_start'],
self.binary_header['sweep_freq_end'],
self.binary_header['sweep_length'],
self.binary_header['sweep_type'],
self.binary_header['sweep_channel'],
self.binary_header['sweep_taper_start'],
self.binary_header['sweep_taper_end'],
self.binary_header['taper_type'],
self.binary_header['correlated_traces'],
self.binary_header['binary_gain'],
self.binary_header['amp_recovery'],
self.binary_header['measurement_system'],
self.binary_header['impulse_polarity'],
self.binary_header['vibratory_polarity'],
self.binary_header['segy_revision'],
self.binary_header['fixed_trace_flag'],
self.binary_header['ext_text_headers'])
# Pad unassigned sections
unassigned1 = b'\x00' * 240 # Bytes 3261-3500
unassigned2 = b'\x00' * 94 # Bytes 3507-3600
f.write(binary_packed[:60] + unassigned1 + binary_packed[60:66] + unassigned2)
# Write trace headers and data similarly (partial)
# Usage example remains the same.
5. Java Class for Handling .Y Files
The Java class has been upgraded to extract all binary file header fields using ByteBuffer. The printProperties and write methods now handle all fields.
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
public class SegYHandler {
private String filepath;
private String textualHeader;
private ByteBuffer binaryHeader;
// Add fields for trace headers and data
public SegYHandler(String filepath) {
this.filepath = filepath;
}
public void read() throws IOException {
try (FileInputStream fis = new FileInputStream(filepath);
DataInputStream dis = new DataInputStream(fis)) {
// Read Textual Header
byte[] textBytes = new byte[3200];
dis.readFully(textBytes);
textualHeader = new String(textBytes, "Cp037");
// Read Binary Header
byte[] binBytes = new byte[400];
dis.readFully(binBytes);
binaryHeader = ByteBuffer.wrap(binBytes).order(ByteOrder.BIG_ENDIAN);
// Extract all properties (accessed via getters in print)
// Read Trace Header (example)
byte[] traceBytes = new byte[240];
dis.readFully(traceBytes);
ByteBuffer traceHeader = ByteBuffer.wrap(traceBytes).order(ByteOrder.BIG_ENDIAN);
// Extract trace fields (partial)
}
}
public void printProperties() {
System.out.println("Textual Header:");
System.out.println(textualHeader);
System.out.println("\nBinary Header:");
System.out.println("Job identification number: " + binaryHeader.getInt(0));
System.out.println("Line number: " + binaryHeader.getInt(4));
System.out.println("Reel number: " + binaryHeader.getInt(8));
System.out.println("Number of data traces per ensemble: " + binaryHeader.getShort(12));
System.out.println("Number of auxiliary traces per ensemble: " + binaryHeader.getShort(14));
System.out.println("Sample interval in microseconds: " + binaryHeader.getShort(16));
System.out.println("Original field sample interval: " + binaryHeader.getShort(18));
System.out.println("Number of samples per data trace: " + binaryHeader.getShort(20));
System.out.println("Original field samples per trace: " + binaryHeader.getShort(22));
System.out.println("Data sample format code: " + binaryHeader.getShort(24));
System.out.println("Ensemble fold: " + binaryHeader.getShort(26));
System.out.println("Trace sorting code: " + binaryHeader.getShort(28));
System.out.println("Vertical sum code: " + binaryHeader.getShort(30));
System.out.println("Sweep frequency at start (Hz): " + binaryHeader.getShort(32));
System.out.println("Sweep frequency at end (Hz): " + binaryHeader.getShort(34));
System.out.println("Sweep length (ms): " + binaryHeader.getShort(36));
System.out.println("Sweep type code: " + binaryHeader.getShort(38));
System.out.println("Trace number of sweep channel: " + binaryHeader.getShort(40));
System.out.println("Sweep trace taper length at start (ms): " + binaryHeader.getShort(42));
System.out.println("Sweep trace taper length at end (ms): " + binaryHeader.getShort(44));
System.out.println("Taper type: " + binaryHeader.getShort(46));
System.out.println("Correlated data traces: " + binaryHeader.getShort(48));
System.out.println("Binary gain recovered: " + binaryHeader.getShort(50));
System.out.println("Amplitude recovery method: " + binaryHeader.getShort(52));
System.out.println("Measurement system: " + binaryHeader.getShort(54));
System.out.println("Impulse signal polarity: " + binaryHeader.getShort(56));
System.out.println("Vibratory polarity code: " + binaryHeader.getShort(58));
// Unassigned 60-300
System.out.println("SEG-Y Format Revision Number: " + binaryHeader.getShort(300)); // Unsigned treated as signed
System.out.println("Fixed length trace flag: " + binaryHeader.getShort(302));
System.out.println("Number of 3200-byte Extended Textual Header records: " + binaryHeader.getShort(304));
// Unassigned 306-400
}
public void write(String outputPath) throws IOException {
try (FileOutputStream fos = new FileOutputStream(outputPath)) {
fos.write(textualHeader.getBytes("Cp037"));
// Write full binary header (copy array, or repack if modified)
fos.write(binaryHeader.array());
// Write trace headers and data (partial)
}
}
// Usage example in main remains the same.
}
6. JavaScript Class for Handling .Y Files
The JavaScript class has been upgraded to extract all binary file header fields into the binaryHeader object.
class SegYHandler {
constructor(file) {
this.file = file;
this.textualHeader = null;
this.binaryHeader = {};
// Add traceHeaders, data
}
async read() {
const arrayBuffer = await this.file.arrayBuffer();
const dataView = new DataView(arrayBuffer);
// Textual Header (approximation)
let textDecoder = new TextDecoder('iso-8859-1');
this.textualHeader = textDecoder.decode(new Uint8Array(arrayBuffer, 0, 3200));
// Binary Header (full extraction)
this.binaryHeader = {
jobId: dataView.getInt32(3200, false),
lineNum: dataView.getInt32(3204, false),
reelNum: dataView.getInt32(3208, false),
dataTracesEnsemble: dataView.getInt16(3212, false),
auxTracesEnsemble: dataView.getInt16(3214, false),
sampleInterval: dataView.getInt16(3216, false),
origSampleInterval: dataView.getInt16(3218, false),
samplesPerTrace: dataView.getInt16(3220, false),
origSamplesPerTrace: dataView.getInt16(3222, false),
formatCode: dataView.getInt16(3224, false),
ensembleFold: dataView.getInt16(3226, false),
traceSorting: dataView.getInt16(3228, false),
verticalSum: dataView.getInt16(3230, false),
sweepFreqStart: dataView.getInt16(3232, false),
sweepFreqEnd: dataView.getInt16(3234, false),
sweepLength: dataView.getInt16(3236, false),
sweepType: dataView.getInt16(3238, false),
sweepChannel: dataView.getInt16(3240, false),
sweepTaperStart: dataView.getInt16(3242, false),
sweepTaperEnd: dataView.getInt16(3244, false),
taperType: dataView.getInt16(3246, false),
correlatedTraces: dataView.getInt16(3248, false),
binaryGain: dataView.getInt16(3250, false),
ampRecovery: dataView.getInt16(3252, false),
measurementSystem: dataView.getInt16(3254, false),
impulsePolarity: dataView.getInt16(3256, false),
vibratoryPolarity: dataView.getInt16(3258, false),
// Unassigned 3260-3499
segyRevision: dataView.getUint16(3500, false),
fixedTraceFlag: dataView.getInt16(3502, false),
extTextHeaders: dataView.getInt16(3504, false),
// Unassigned 3506-3599
};
// Trace Header (partial)
this.traceHeader = {};
this.traceHeader.traceSeqLine = dataView.getInt32(3600, false);
// ...
}
printProperties() {
console.log('Textual Header:', this.textualHeader);
console.log('Binary Header:', this.binaryHeader);
// Log trace (partial)
}
async write() {
// Simplified: Create new buffer, pack all fields
const newBuffer = new ArrayBuffer(3600 + /* trace size */);
const newView = new DataView(newBuffer);
newView.setInt32(3200, this.binaryHeader.jobId, false);
newView.setInt32(3204, this.binaryHeader.lineNum, false);
newView.setInt32(3208, this.binaryHeader.reelNum, false);
newView.setInt16(3212, this.binaryHeader.dataTracesEnsemble, false);
newView.setInt16(3214, this.binaryHeader.auxTracesEnsemble, false);
newView.setInt16(3216, this.binaryHeader.sampleInterval, false);
newView.setInt16(3218, this.binaryHeader.origSampleInterval, false);
newView.setInt16(3220, this.binaryHeader.samplesPerTrace, false);
newView.setInt16(3222, this.binaryHeader.origSamplesPerTrace, false);
newView.setInt16(3224, this.binaryHeader.formatCode, false);
newView.setInt16(3226, this.binaryHeader.ensembleFold, false);
newView.setInt16(3228, this.binaryHeader.traceSorting, false);
newView.setInt16(3230, this.binaryHeader.verticalSum, false);
newView.setInt16(3232, this.binaryHeader.sweepFreqStart, false);
newView.setInt16(3234, this.binaryHeader.sweepFreqEnd, false);
newView.setInt16(3236, this.binaryHeader.sweepLength, false);
newView.setInt16(3238, this.binaryHeader.sweepType, false);
newView.setInt16(3240, this.binaryHeader.sweepChannel, false);
newView.setInt16(3242, this.binaryHeader.sweepTaperStart, false);
newView.setInt16(3244, this.binaryHeader.sweepTaperEnd, false);
newView.setInt16(3246, this.binaryHeader.taperType, false);
newView.setInt16(3248, this.binaryHeader.correlatedTraces, false);
newView.setInt16(3250, this.binaryHeader.binaryGain, false);
newView.setInt16(3252, this.binaryHeader.ampRecovery, false);
newView.setInt16(3254, this.binaryHeader.measurementSystem, false);
newView.setInt16(3256, this.binaryHeader.impulsePolarity, false);
newView.setInt16(3258, this.binaryHeader.vibratoryPolarity, false);
newView.setUint16(3500, this.binaryHeader.segyRevision, false);
newView.setInt16(3502, this.binaryHeader.fixedTraceFlag, false);
newView.setInt16(3504, this.binaryHeader.extTextHeaders, false);
// Pack textual and traces similarly
const blob = new Blob([newBuffer]);
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'output.sgy';
a.click();
}
}
// Usage example remains the same.
7. C++ Class for Handling .Y Files
The C++ class has been upgraded with a complete BinaryHeader struct containing all fields, using memcpy for extraction and packing. Endian conversion is assumed unnecessary if host matches big-endian; otherwise, add swapping.
#include <iostream>
#include <fstream>
#include <vector>
#include <cstring>
#include <cstdint> // For fixed-width types
class SegYHandler {
private:
std::string filepath;
std::string textualHeader;
struct BinaryHeader {
int32_t jobId;
int32_t lineNum;
int32_t reelNum;
int16_t dataTracesEnsemble;
int16_t auxTracesEnsemble;
int16_t sampleInterval;
int16_t origSampleInterval;
int16_t samplesPerTrace;
int16_t origSamplesPerTrace;
int16_t formatCode;
int16_t ensembleFold;
int16_t traceSorting;
int16_t verticalSum;
int16_t sweepFreqStart;
int16_t sweepFreqEnd;
int16_t sweepLength;
int16_t sweepType;
int16_t sweepChannel;
int16_t sweepTaperStart;
int16_t sweepTaperEnd;
int16_t taperType;
int16_t correlatedTraces;
int16_t binaryGain;
int16_t ampRecovery;
int16_t measurementSystem;
int16_t impulsePolarity;
int16_t vibratoryPolarity;
uint16_t segyRevision; // Unsigned
int16_t fixedTraceFlag;
int16_t extTextHeaders;
} binaryHeader;
// Add trace struct
public:
SegYHandler(const std::string& fp) : filepath(fp) {}
void read() {
std::ifstream file(filepath, std::ios::binary);
if (!file) return;
// Textual Header
std::vector<char> textBuf(3200);
file.read(textBuf.data(), 3200);
textualHeader = std::string(textBuf.begin(), textBuf.end()); // EBCDIC conversion needed
// Binary Header
char binBuf[400];
file.read(binBuf, 400);
memcpy(&binaryHeader.jobId, binBuf + 0, 4);
memcpy(&binaryHeader.lineNum, binBuf + 4, 4);
memcpy(&binaryHeader.reelNum, binBuf + 8, 4);
memcpy(&binaryHeader.dataTracesEnsemble, binBuf + 12, 2);
memcpy(&binaryHeader.auxTracesEnsemble, binBuf + 14, 2);
memcpy(&binaryHeader.sampleInterval, binBuf + 16, 2);
memcpy(&binaryHeader.origSampleInterval, binBuf + 18, 2);
memcpy(&binaryHeader.samplesPerTrace, binBuf + 20, 2);
memcpy(&binaryHeader.origSamplesPerTrace, binBuf + 22, 2);
memcpy(&binaryHeader.formatCode, binBuf + 24, 2);
memcpy(&binaryHeader.ensembleFold, binBuf + 26, 2);
memcpy(&binaryHeader.traceSorting, binBuf + 28, 2);
memcpy(&binaryHeader.verticalSum, binBuf + 30, 2);
memcpy(&binaryHeader.sweepFreqStart, binBuf + 32, 2);
memcpy(&binaryHeader.sweepFreqEnd, binBuf + 34, 2);
memcpy(&binaryHeader.sweepLength, binBuf + 36, 2);
memcpy(&binaryHeader.sweepType, binBuf + 38, 2);
memcpy(&binaryHeader.sweepChannel, binBuf + 40, 2);
memcpy(&binaryHeader.sweepTaperStart, binBuf + 42, 2);
memcpy(&binaryHeader.sweepTaperEnd, binBuf + 44, 2);
memcpy(&binaryHeader.taperType, binBuf + 46, 2);
memcpy(&binaryHeader.correlatedTraces, binBuf + 48, 2);
memcpy(&binaryHeader.binaryGain, binBuf + 50, 2);
memcpy(&binaryHeader.ampRecovery, binBuf + 52, 2);
memcpy(&binaryHeader.measurementSystem, binBuf + 54, 2);
memcpy(&binaryHeader.impulsePolarity, binBuf + 56, 2);
memcpy(&binaryHeader.vibratoryPolarity, binBuf + 58, 2);
// Unassigned 60-300
memcpy(&binaryHeader.segyRevision, binBuf + 300, 2);
memcpy(&binaryHeader.fixedTraceFlag, binBuf + 302, 2);
memcpy(&binaryHeader.extTextHeaders, binBuf + 304, 2);
// Unassigned 306-400
// Trace Header (partial)
}
void printProperties() {
std::cout << "Textual Header:" << std::endl << textualHeader << std::endl;
std::cout << "Binary Header:" << std::endl;
std::cout << "Job ID: " << binaryHeader.jobId << std::endl;
std::cout << "Line Number: " << binaryHeader.lineNum << std::endl;
std::cout << "Reel Number: " << binaryHeader.reelNum << std::endl;
std::cout << "Data Traces per Ensemble: " << binaryHeader.dataTracesEnsemble << std::endl;
std::cout << "Auxiliary Traces per Ensemble: " << binaryHeader.auxTracesEnsemble << std::endl;
std::cout << "Sample Interval: " << binaryHeader.sampleInterval << std::endl;
std::cout << "Original Sample Interval: " << binaryHeader.origSampleInterval << std::endl;
std::cout << "Samples per Trace: " << binaryHeader.samplesPerTrace << std::endl;
std::cout << "Original Samples per Trace: " << binaryHeader.origSamplesPerTrace << std::endl;
std::cout << "Format Code: " << binaryHeader.formatCode << std::endl;
std::cout << "Ensemble Fold: " << binaryHeader.ensembleFold << std::endl;
std::cout << "Trace Sorting: " << binaryHeader.traceSorting << std::endl;
std::cout << "Vertical Sum: " << binaryHeader.verticalSum << std::endl;
std::cout << "Sweep Freq Start: " << binaryHeader.sweepFreqStart << std::endl;
std::cout << "Sweep Freq End: " << binaryHeader.sweepFreqEnd << std::endl;
std::cout << "Sweep Length: " << binaryHeader.sweepLength << std::endl;
std::cout << "Sweep Type: " << binaryHeader.sweepType << std::endl;
std::cout << "Sweep Channel: " << binaryHeader.sweepChannel << std::endl;
std::cout << "Sweep Taper Start: " << binaryHeader.sweepTaperStart << std::endl;
std::cout << "Sweep Taper End: " << binaryHeader.sweepTaperEnd << std::endl;
std::cout << "Taper Type: " << binaryHeader.taperType << std::endl;
std::cout << "Correlated Traces: " << binaryHeader.correlatedTraces << std::endl;
std::cout << "Binary Gain: " << binaryHeader.binaryGain << std::endl;
std::cout << "Amp Recovery: " << binaryHeader.ampRecovery << std::endl;
std::cout << "Measurement System: " << binaryHeader.measurementSystem << std::endl;
std::cout << "Impulse Polarity: " << binaryHeader.impulsePolarity << std::endl;
std::cout << "Vibratory Polarity: " << binaryHeader.vibratoryPolarity << std::endl;
std::cout << "SEG-Y Revision: " << binaryHeader.segyRevision << std::endl;
std::cout << "Fixed Trace Flag: " << binaryHeader.fixedTraceFlag << std::endl;
std::cout << "Extended Text Headers: " << binaryHeader.extTextHeaders << std::endl;
}
void write(const std::string& outputPath) {
std::ofstream out(outputPath, std::ios::binary);
out.write(textualHeader.c_str(), 3200);
char binBuf[400] = {0};
memcpy(binBuf + 0, &binaryHeader.jobId, 4);
memcpy(binBuf + 4, &binaryHeader.lineNum, 4);
memcpy(binBuf + 8, &binaryHeader.reelNum, 4);
memcpy(binBuf + 12, &binaryHeader.dataTracesEnsemble, 2);
memcpy(binBuf + 14, &binaryHeader.auxTracesEnsemble, 2);
memcpy(binBuf + 16, &binaryHeader.sampleInterval, 2);
memcpy(binBuf + 18, &binaryHeader.origSampleInterval, 2);
memcpy(binBuf + 20, &binaryHeader.samplesPerTrace, 2);
memcpy(binBuf + 22, &binaryHeader.origSamplesPerTrace, 2);
memcpy(binBuf + 24, &binaryHeader.formatCode, 2);
memcpy(binBuf + 26, &binaryHeader.ensembleFold, 2);
memcpy(binBuf + 28, &binaryHeader.traceSorting, 2);
memcpy(binBuf + 30, &binaryHeader.verticalSum, 2);
memcpy(binBuf + 32, &binaryHeader.sweepFreqStart, 2);
memcpy(binBuf + 34, &binaryHeader.sweepFreqEnd, 2);
memcpy(binBuf + 36, &binaryHeader.sweepLength, 2);
memcpy(binBuf + 38, &binaryHeader.sweepType, 2);
memcpy(binBuf + 40, &binaryHeader.sweepChannel, 2);
memcpy(binBuf + 42, &binaryHeader.sweepTaperStart, 2);
memcpy(binBuf + 44, &binaryHeader.sweepTaperEnd, 2);
memcpy(binBuf + 46, &binaryHeader.taperType, 2);
memcpy(binBuf + 48, &binaryHeader.correlatedTraces, 2);
memcpy(binBuf + 50, &binaryHeader.binaryGain, 2);
memcpy(binBuf + 52, &binaryHeader.ampRecovery, 2);
memcpy(binBuf + 54, &binaryHeader.measurementSystem, 2);
memcpy(binBuf + 56, &binaryHeader.impulsePolarity, 2);
memcpy(binBuf + 58, &binaryHeader.vibratoryPolarity, 2);
memcpy(binBuf + 300, &binaryHeader.segyRevision, 2);
memcpy(binBuf + 302, &binaryHeader.fixedTraceFlag, 2);
memcpy(binBuf + 304, &binaryHeader.extTextHeaders, 2);
out.write(binBuf, 400);
// Write traces (partial)
}
};
// Usage example remains the same.