Skip to content

Commit

Permalink
Merge pull request #19 from kerim371/add-segy-endian-check
Browse files Browse the repository at this point in the history
Add segy endian check
  • Loading branch information
mloubout committed Jun 7, 2023
2 parents 8777868 + d7b3c77 commit 61125ad
Show file tree
Hide file tree
Showing 12 changed files with 134 additions and 48 deletions.
1 change: 1 addition & 0 deletions src/SegyIO.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ module SegyIO
include("types/SeisCon.jl")

#Reader
include("read/endianness.jl")
include("read/read_fileheader.jl")
include("read/read_traceheader.jl")
include("read/read_trace.jl")
Expand Down
68 changes: 68 additions & 0 deletions src/read/endianness.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
is_machine_littleendian() = Base.ENDIAN_BOM == 0x04030201
is_machine_bigendian() = Base.ENDIAN_BOM == 0x01020304

function is_segy_littleendian(s::IO)
bfh = BinaryFileHeader()
fh_b2s = fh_byte2sample()

old_pos = position(s)
seek(s, fh_b2s["DataSampleFormat"])
dsf = read(s, typeof(bfh.DataSampleFormat))
dsf_bs = bswap(dsf)
seek(s, old_pos)

if (dsf >= 1 && dsf <= 16 && is_machine_littleendian()) ||
(dsf_bs >= 1 && dsf_bs <= 16 && is_machine_bigendian())
return true
else
return false
end
end

function is_segy_bigendian(s::IO)
bfh = BinaryFileHeader()
fh_b2s = fh_byte2sample()

old_pos = position(s)
seek(s, fh_b2s["DataSampleFormat"])
dsf = read(s, typeof(bfh.DataSampleFormat))
dsf = bswap(read(s, typeof(bfh.DataSampleFormat)))
seek(s, old_pos)

if (dsf >= 1 && dsf <= 16 && is_machine_bigendian()) ||
(dsf_bs >= 1 && dsf_bs <= 16 && is_machine_littleendian())
return true
else
return false
end
end


"""
bswap_needed(s::IO)
Checks whether SEGY and host machine's byte order are same or not.
NOTE: comparison is done based on binary file header value (Data Sample Format)
thus stream (s::IO) must be opened from the begining of the file.
# Examples
s = open("/my/segy.segy", "r")
swap_bytes = bswap_needed(s)
"""
function bswap_needed(s::IO)
bfh = BinaryFileHeader()
fh_b2s = fh_byte2sample()

old_pos = position(s)
seek(s, fh_b2s["DataSampleFormat"])
dsf = read(s, typeof(bfh.DataSampleFormat))
seek(s, old_pos)

if dsf >= 1 && dsf <= 16
return false
else
return true
end
end
3 changes: 2 additions & 1 deletion src/read/read_block.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ end
function read_block!(b::BlockScan, keys::Array{String, 1}, ns::Int, dsf::Int, tmp_data, tmp_headers)

f = open(b.file)
swap_bytes = bswap_needed(f)
seek(f, b.startbyte)
brange = b.endbyte - b.startbyte
s = IOBuffer(read(f, brange))
Expand All @@ -29,6 +30,6 @@ function read_block!(b::BlockScan, keys::Array{String, 1}, ns::Int, dsf::Int, tm
tracee = min(trace + TRACE_CHUNKSIZE - 1, ntraces)
chunk = length(trace:tracee)*trace_size
sloc = IOBuffer(read(s, chunk))
read_traces!(sloc, view(tmp_headers, trace:tracee), view(tmp_data, :, trace:tracee), keys, th_b2s)
read_traces!(sloc, view(tmp_headers, trace:tracee), view(tmp_data, :, trace:tracee), keys, th_b2s; swap_bytes=swap_bytes)
end
end
6 changes: 4 additions & 2 deletions src/read/read_block_headers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export read_block_headers!
function read_block_headers!(b::BlockScan, keys::Array{String, 1}, ns::Int, dsf::Int, headers)

f = open(b.file)
swap_bytes = bswap_needed(f)
seek(f, b.startbyte)
brange = b.endbyte - b.startbyte
s = IOBuffer(read(f, brange))
Expand All @@ -23,7 +24,7 @@ function read_block_headers!(b::BlockScan, keys::Array{String, 1}, ns::Int, dsf:
tmph = zeros(UInt8, 240)
# Read each traceheader
for trace in 1:ntraces
read_traceheader!(s, keys, th_b2s, headers[trace]; th=tmph)
read_traceheader!(s, keys, th_b2s, headers[trace]; swap_bytes=swap_bytes, th=tmph)
skip(s, ns*4)
end

Expand All @@ -32,6 +33,7 @@ end
function read_block_headers!(b::BlockScan, ns::Int, dsf::Int, headers)

f = open(b.file)
swap_bytes = bswap_needed(f)
seek(f, b.startbyte)
brange = b.endbyte - b.startbyte
s = IOBuffer(read(f, brange))
Expand All @@ -50,7 +52,7 @@ function read_block_headers!(b::BlockScan, ns::Int, dsf::Int, headers)
th_b2s = th_byte2sample()
# Read each traceheader
for trace in 1:ntraces
read_traceheader!(s, th_b2s, headers[trace])
read_traceheader!(s, th_b2s, headers[trace]; swap_bytes=swap_bytes)
skip(s, ns*4)
end

Expand Down
7 changes: 5 additions & 2 deletions src/read/read_file.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@ Read entire SEGY file from stream 's', only reading the header values in 'keys'.
"""
function read_file(s::IO, keys::Array{String, 1}, warn_user::Bool;
start_byte::Int = 3600, end_byte::Int = position(seekend(s)))

swap_bytes = bswap_needed(s)

# Read File Header
fh = read_fileheader(s)
fh = read_fileheader(s; swap_bytes=swap_bytes)

# Move to start of block
seek(s, start_byte)
Expand Down Expand Up @@ -53,7 +56,7 @@ function read_file(s::IO, keys::Array{String, 1}, warn_user::Bool;
tracee = min(trace + TRACE_CHUNKSIZE - 1, ntraces)
chunk = length(trace:tracee)*trace_size
sloc = IOBuffer(read(s, chunk))
read_traces!(sloc, view(headers, trace:tracee), view(data, :, trace:tracee), keys, th_b2s)
read_traces!(sloc, view(headers, trace:tracee), view(data, :, trace:tracee), keys, th_b2s; swap_bytes=swap_bytes)
end

return SeisBlock(fh, headers, data)
Expand Down
12 changes: 6 additions & 6 deletions src/read/read_fileheader.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@ export read_fileheader
"""
# Info
Use: fileheader = read_fileheader(s::IO; bigendian::Bool = true)
Use: fileheader = read_fileheader(s::IO; swap_bytes::Bool = bswap_needed(s))
Returns a binary file header formed using bytes 3200-3600 from the stream 's'.
"""
function read_fileheader(s::IO; bigendian::Bool = true)
return read_fileheader(s, fh_keys(); bigendian=bigendian)
function read_fileheader(s::IO; swap_bytes::Bool = bswap_needed(s))
return read_fileheader(s, fh_keys(); swap_bytes=swap_bytes)
end


"""
Use: fileheader = read_fileheader(s::IO, keys::Array{String,1}; bigendian::Bool = true)
Use: fileheader = read_fileheader(s::IO, keys::Array{String,1}; swap_bytes::Bool = bswap_needed(s))
Return a fileheader from stream 's' with the fields defined in 'keys'.
Expand All @@ -41,7 +41,7 @@ Read only the sample interval and number of traces from the file header.
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Dict("expf"=>3226,"sfe"=>3234,"rgc"=>3250,"jobid"=>3200,
"dt"=>3216,"nsfr"=>3222,"slen"=>3236,"vpol"=>3258,"renum"=>3208,"dsf"=>3224…))
"""
function read_fileheader(s::IO, keys::Array{String,1}; bigendian::Bool = true)
function read_fileheader(s::IO, keys::Array{String,1}; swap_bytes::Bool = bswap_needed(s))

# Return to start of stream
seekstart(s)
Expand All @@ -52,7 +52,7 @@ function read_fileheader(s::IO, keys::Array{String,1}; bigendian::Bool = true)
# Initialize binary file header
bfh = BinaryFileHeader()
fh_b2s = fh_byte2sample()
swp(x) = bigendian ? bswap(x) : x
swp(x) = swap_bytes ? bswap(x) : x

for k in keys

Expand Down
27 changes: 13 additions & 14 deletions src/read/read_trace.jl
Original file line number Diff line number Diff line change
@@ -1,54 +1,53 @@
export read_trace
export read_traces

"""
Use: read_trace!(s::IO,
Use: read_traces!(s::IO,
fh::BinaryFileHeader,
datatype::Type,
headers::AbstractArray{BinaryTraceHeader,1},
data::AbstractArray{<:Union{IBMFloat32, Float32}, 2},
trace::Int,
th_byte2sample::Dict{String,Int32})
th_byte2sample::Dict{String,Int32};
swap_bytes::Bool)
Reads 'trace' from the current position of stream 's' into 'headers' and
'data'.
"""
function read_traces!(s::IO, headers::AbstractVector{BinaryTraceHeader},
data::AbstractMatrix{<:Union{IBMFloat32, Float32}},
th_byte2sample::Dict{String,Int32})
th_byte2sample::Dict{String,Int32};
swap_bytes::Bool)

return read_traces!(s, headers, data, collect(keys(th_byte2sample)), th_byte2sample)
return read_traces!(s, headers, data, collect(keys(th_byte2sample)), th_byte2sample; swap_bytes=swap_bytes)
end

"""
Use: read_trace!(s::IO,
Use: read_traces!(s::IO,
fh::BinaryFileHeader,
datatype::Type,
headers::AbstractArray{BinaryTraceHeader,1},
data::AbstractArray{<:Union{IBMFloat32, Float32}, 2},
trace::Int,
keys::Array{String,1},
th_byte2sample::Dict{String,Int32})
th_byte2sample::Dict{String,Int32};
swap_bytes::Bool)
Reads 'trace' from the current position of stream 's' into 'headers' and
'data'. Only the header values in 'keys' and read.
"""
function read_traces!(s::IO, headers::AbstractVector{BinaryTraceHeader},
data::AbstractMatrix{DT}, keys::Array{String,1},
th_byte2sample::Dict{String,Int32}) where {DT<:Union{IBMFloat32, Float32}}
th_byte2sample::Dict{String,Int32}; swap_bytes::Bool) where {DT<:Union{IBMFloat32, Float32}}

ntrace = size(data, 2)
ntrace == 0 && return
swp = swp_func(DT)
tmph = zeros(UInt8, 240)
for trace_loc=0:ntrace-1
# Read trace header
read_traceheader!(s, keys, th_byte2sample, headers[trace_loc+1]; th=tmph)
read_traceheader!(s, keys, th_byte2sample, headers[trace_loc+1]; swap_bytes=swap_bytes, th=tmph)
# Read trace
read!(s, view(data, :, trace_loc+1))
end
map!(swp, data, data)
(swap_bytes) && (data = bswap.(data))
nothing
end

swp_func(::Type{Float32}) = bswap
swp_func(::Any) = x -> x
22 changes: 11 additions & 11 deletions src/read/read_traceheader.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,34 @@ export read_traceheader
"""
# Info
Use: fileheader = read_fileheader(s::IO; bigendian::Bool = true)
Use: fileheader = read_fileheader(s::IO; swap_bytes::Bool)
Returns a binary trace header formed from the current position in the stream 's'.
"""
function read_traceheader(s::IO, th_byte2sample::Dict{String,Int32}; bigendian::Bool=true, th=zeros(UInt8, 240))
return read_traceheader(s, collect(keys(th_byte2sample)), th_byte2sample; bigendian=bigendian, th=th)
function read_traceheader(s::IO, th_byte2sample::Dict{String,Int32}; swap_bytes::Bool, th=zeros(UInt8, 240))
return read_traceheader(s, collect(keys(th_byte2sample)), th_byte2sample; swap_bytes=swap_bytes, th=th)
end

"""
Use: fileheader = read_traceheader(s::IO, keys = Array{String,1}; bigendian::Bool = true)
Use: fileheader = read_traceheader(s::IO, keys = Array{String,1}; swap_bytes::Bool)
Returns a binary trace header formed from the current position in the stream 's', only reading
header values denoted in 'keys'.
"""
function read_traceheader(s::IO, keys::Array{String,1}, th_byte2sample::Dict{String, Int32};
bigendian::Bool = true, th=zeros(UInt8, 240))
swap_bytes::Bool, th=zeros(UInt8, 240))

# Initialize binary file header
traceheader = BinaryTraceHeader()

read_traceheader!(s, keys, th_byte2sample, traceheader; bigendian=bigendian, th=th)
read_traceheader!(s, keys, th_byte2sample, traceheader; swap_bytes=swap_bytes, th=th)
return traceheader
end

function read_traceheader!(s::IO, keys::Array{String,1}, th_byte2sample::Dict{String, Int32}, hdr::BinaryTraceHeader;
bigendian::Bool = true, th=zeros(UInt8, 240))

swap_bytes::Bool, th=zeros(UInt8, 240))
# read full trace header then split
read!(s, th)

Expand All @@ -40,11 +40,11 @@ function read_traceheader!(s::IO, keys::Array{String,1}, th_byte2sample::Dict{St
nb = sizeof(getfield(hdr, sym)) - 1
bst = th_byte2sample[k]+1
val = reinterpret(typeof(getfield(hdr, sym)), th[bst:bst+nb])[1]
bigendian && (val = bswap(val))
swap_bytes && (val = bswap(val))
setfield!(hdr, sym, val)
end
nothing
end

read_traceheader!(s::IO, thb::Dict{String, Int32}, hdr::BinaryTraceHeader; be::Bool = true, th=zeros(UInt8, 240)) =
read_traceheader!(s, collect(keys(thb)), thb, hdr; be=be, th=th)
read_traceheader!(s::IO, thb::Dict{String, Int32}, hdr::BinaryTraceHeader; swap_bytes::Bool, th=zeros(UInt8, 240)) =
read_traceheader!(s, collect(keys(thb)), thb, hdr; swap_bytes=swap_bytes, th=th)
8 changes: 6 additions & 2 deletions src/scan/scan_block.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ export scan_block

function scan_block(buf::IO, mem_block::Int, mem_trace::Int, keys::Array{String,1},
chunk_start::Int, file::String, th_byte2sample::Dict{String, Int32})


f = open(file)
swap_bytes = bswap_needed(f)
close(f)

# Calc info about this block
startbyte = position(buf) + chunk_start
ntraces_block = Int(mem_block/mem_trace)
Expand All @@ -12,7 +16,7 @@ function scan_block(buf::IO, mem_block::Int, mem_trace::Int, keys::Array{String,
# Read all headers and record end byte
while !eof(buf) && count<ntraces_block
count += 1
read_traceheader!(buf, keys, th_byte2sample, headers[count] )
read_traceheader!(buf, keys, th_byte2sample, headers[count]; swap_bytes=swap_bytes)
skip(buf, mem_trace-240)
end
endbyte = position(buf) + chunk_start
Expand Down
6 changes: 5 additions & 1 deletion src/scan/scan_shots.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ export scan_shots
function scan_shots!(s::IO, mem_chunk::Int, mem_trace::Int,
keys::Array{String,1}, file::AbstractString, scan::Array{BlockScan,1}, fl_eof::Bool)

f = open(file)
swap_bytes = bswap_needed(f)
close(f)

# Load chunk into memory
chunk_start = position(s)
buf = IOBuffer(read(s, mem_chunk))
Expand All @@ -14,7 +18,7 @@ function scan_shots!(s::IO, mem_chunk::Int, mem_trace::Int,
# Get headers from chunk
th = zeros(UInt8, 240)
for i in 1:ntraces
read_traceheader!(buf, keys, SegyIO.th_b2s, headers[i]; th=th)
read_traceheader!(buf, keys, SegyIO.th_b2s, headers[i]; swap_bytes=swap_bytes, th=th)
skip(buf, mem_trace-240)
end

Expand Down
6 changes: 5 additions & 1 deletion src/types/IBMFloat32.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ primitive type IBMFloat32 32 end
ieeeOfPieces(fr::UInt32, exp::Int32, sgn::UInt32) =
reinterpret(Float32, convert(UInt32,fr >>> 9) | convert(UInt32,exp << 23) | sgn) :: Float32

import Base.convert, Base.Float32
import Base.convert, Base.Float32, Base.bswap

function convert(::Type{Float32}, ibm::IBMFloat32)
local fr::UInt32 = ntoh(reinterpret(UInt32, ibm))
Expand All @@ -29,3 +29,7 @@ function convert(::Type{Float32}, ibm::IBMFloat32)
end
Float32(ibm::IBMFloat32) = convert(Float32,ibm)
## From JuliaSeis

function bswap(ibm::IBMFloat32)
return reinterpret(IBMFloat32, bswap(reinterpret(UInt32, ibm)))
end
Loading

0 comments on commit 61125ad

Please sign in to comment.