Skip to content

Commit

Permalink
Fix bug and add consistency tests. (#20)
Browse files Browse the repository at this point in the history
* Fix "bytesize not defined" and add tests.

* Format the codes.

* Add consistency tests and fix bugs.

* Format the codes.

* Move PyCall to [extras]

* Using Conda to install packages for tests.

* Using conda.

* Using CondPkg and PythonCall.

* Update Project.toml

Co-authored-by: Seth Axen <[email protected]>

* Update Project.toml

Co-authored-by: Seth Axen <[email protected]>

* Update test/consistency.jl

Co-authored-by: Seth Axen <[email protected]>

* Update test/runtests.jl

Co-authored-by: Seth Axen <[email protected]>

* Update consistency.jl

* Update CondaPkg.toml.

---------

Co-authored-by: Seth Axen <[email protected]>
  • Loading branch information
shuuul and sethaxen authored Jul 17, 2023
1 parent f82d9f5 commit 8fae385
Show file tree
Hide file tree
Showing 8 changed files with 117 additions and 7 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
*.jl.cov
*.jl.mem
/docs/build/
Manifest.toml
Manifest.toml
/.CondaPkg
3 changes: 3 additions & 0 deletions CondaPkg.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[deps]
mrcfile = ">=1.2,<2.0"
numpy = ">=1.1,<2.0"
6 changes: 4 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "MRCFile"
uuid = "c18c01d3-0ab9-49c3-bd2d-8f2e64a2b7a5"
authors = ["Seth Axen <[email protected]>"]
version = "0.1.1"
version = "0.1.2"

[deps]
CodecBzip2 = "523fee87-0ab8-5b00-afb7-3ecf72e48cfd"
Expand All @@ -20,7 +20,9 @@ TranscodingStreams = "0.9"
julia = "^1"

[extras]
CondaPkg = "992eb4ea-22a4-4c89-a5bb-47a3300528ab"
PythonCall = "6099a3de-0909-46bc-b1f4-468b9a2dfc0d"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["Test"]
test = ["CondaPkg", "PythonCall", "Test"]
2 changes: 1 addition & 1 deletion src/header.jl
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ function sizeoffield(name, type)
end

function bytestoentry(name, type, pointer)
name === :exttyp && return _unsafe_string(pointer, 4)
name === :exttyp && return unsafe_string(convert(Ptr{UInt8}, pointer), 4)
name === :map && return _unsafe_string(pointer, 4)
name === :label && return ntuple(Val(10)) do i
return strip(_unsafe_string(pointer + (i - 1) * 80, 80), ' ')
Expand Down
2 changes: 1 addition & 1 deletion src/io.jl
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ Read MRC file or stream, using a memory-mapped array to access the data.
function read_mmap(io::IO, ::Type{MRCData})
head = read(io, MRCHeader)
exthead = read(io, MRCExtendedHeader; header=head)
arraytype = Array{MRC.datatype(head),ndims(head)}
arraytype = Array{datatype(head),ndims(head)}
data = Mmap.mmap(io, arraytype, size(head)[1:ndims(head)])
return MRCData(head, exthead, data)
end
Expand Down
97 changes: 97 additions & 0 deletions test/consistency.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
using Test
using CondaPkg
using PythonCall

# Load the Python module/package
numpy = pyimport("numpy")
mrcfile = pyimport("mrcfile")

function compare_map(map_jl::Array{Float32,3}, map_py::Array{Float32,3})
# dimensions permuted due to row-major storage in Python and col-major in Julia
# see https://github.com/sethaxen/MRCFile.jl/issues/10
@test_broken map_jl == map_py
permuted_py = permutedims(map_py, (3, 2, 1))
@test map_jl == permuted_py
end

function compare_header(header_jl::MRCHeader, header_py::Py)
@test Bool(header_jl.nx == header_py.nx)
@test Bool(header_jl.ny == header_py.ny)
@test Bool(header_jl.nz == header_py.nz)
@test Bool(header_jl.mode == header_py.mode)
@test Bool(header_jl.nxstart == header_py.nxstart)
@test Bool(header_jl.nystart == header_py.nystart)
@test Bool(header_jl.nzstart == header_py.nzstart)
@test Bool(header_jl.mx == header_py.mx)
@test Bool(header_jl.my == header_py.my)
@test Bool(header_jl.mz == header_py.mz)
@test Bool(header_jl.cella_x == header_py.cella.x)
@test Bool(header_jl.cella_y == header_py.cella.y)
@test Bool(header_jl.cella_z == header_py.cella.z)
@test Bool(header_jl.cellb_alpha == header_py.cellb.alpha)
@test Bool(header_jl.cellb_beta == header_py.cellb.beta)
@test Bool(header_jl.cellb_gamma == header_py.cellb.gamma)
@test Bool(header_jl.mapc == header_py.mapc)
@test Bool(header_jl.mapr == header_py.mapr)
@test Bool(header_jl.maps == header_py.maps)
@test Bool(header_jl.dmin == header_py.dmin)
@test Bool(header_jl.dmax == header_py.dmax)
@test Bool(header_jl.dmean == header_py.dmean)
@test Bool(header_jl.ispg == header_py.ispg)
@test Bool(header_jl.nsymbt == header_py.nsymbt)
@test [UInt8(b) for b in header_jl.extra1] == pyconvert(Vector{UInt8}, header_py.extra1.tobytes())
@test [UInt8(b) for b in header_jl.exttyp] == pyconvert(Vector{UInt8}, header_py.exttyp.tobytes())
@test Bool(header_jl.nversion == header_py.nversion)
@test ([UInt8(b) for b in header_jl.extra2]) == pyconvert(Vector{UInt8}, header_py.extra2.tobytes())
@test Bool(header_jl.origin_x == header_py.origin.x)
@test Bool(header_jl.origin_y == header_py.origin.y)
@test Bool(header_jl.origin_z == header_py.origin.z)
@test [UInt8(b) for b in header_jl.map] == pyconvert(Vector{UInt8}, header_py.map.tobytes())
@test [UInt8(b) for b in header_jl.machst] == pyconvert(Vector{UInt8}, header_py.machst.tobytes())
@test Bool(header_jl.rms == header_py.rms)
@test Bool(header_jl.nlabl == header_py.nlabl)
@test join(header_jl.label) ==
pyconvert(String, header_py.label.tostring().decode().strip())
end

function compare_extendedheader(exh_jl::MRCExtendedHeader, exh_py::Py)
@test [UInt8(b) for b in exh_jl.data] == pyconvert(Vector{UInt8}, exh_py.tobytes())
end

function compare_mrcfile(map_path::String)
emd_jl = read(map_path, MRCData)
map_jl = emd_jl.data
header_jl = header(emd_jl)
exh_jl = extendedheader(emd_jl)

emd_py = mrcfile.open(map_path; mode="r")
data_copy = numpy.copy(emd_py.data) # Create a copy of the data
map_py = pyconvert(Array{Float32,3}, data_copy)
header_py = emd_py.header
exh_py = emd_py.extended_header
emd_py.close() # Make sure the file is closed even if an error occurs

@testset "map" begin
compare_map(map_jl, map_py)
end

@testset "header" begin
compare_header(header_jl, header_py)
end

@testset "extendedheader" begin
compare_extendedheader(exh_jl, exh_py)
end
end

@testset "Consistency Test" begin
@testset "emd_3001.map" begin
emd3001_path = "$(@__DIR__)/testdata/emd_3001.map"
compare_mrcfile(emd3001_path)
end

@testset "emd_3197" begin
emd3197_path = "$(@__DIR__)/testdata/emd_3197.map"
compare_mrcfile(emd3197_path)
end
end
10 changes: 8 additions & 2 deletions test/io.jl
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
@test h.ispg === Int32(4)
@test h.nsymbt == sizeof(eh) == Int32(160)
@test h.extra1 === Tuple(zeros(UInt8, 8))
@test h.exttyp === ""
@test h.exttyp === "\0\0\0\0"
@test h.nversion === Int32(0)
@test h.extra2 === Tuple(zeros(UInt8, 84))
@test h.origin_x === Float32(0)
Expand Down Expand Up @@ -80,7 +80,7 @@
@test h.ispg === Int32(1)
@test h.nsymbt == sizeof(eh) == Int32(0)
@test h.extra1 === Tuple(zeros(UInt8, 8))
@test h.exttyp === ""
@test h.exttyp === "\0\0\0\0"
@test h.nversion === Int32(0)
@test h.extra2 === Tuple(zeros(UInt8, 84))
@test h.origin_x === Float32(0)
Expand All @@ -96,6 +96,12 @@
end
end

@testset "read_mmap" begin
emd3001 = read("$(@__DIR__)/testdata/emd_3001.map", MRCData)
emd3001mmap = read_mmap("$(@__DIR__)/testdata/emd_3001.map", MRCData)
@test emd3001 == emd3001mmap
end

@testset "write" begin
@testset "buffer size has no effect on data" begin
emd3001 = read("$(@__DIR__)/testdata/emd_3001.map", MRCData)
Expand Down
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ using Test
include("header.jl")
include("io.jl")
include("data.jl")
VERSION >= v"1.6" && include("consistency.jl")
end

2 comments on commit 8fae385

@sethaxen
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/87626

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.1.2 -m "<description of version>" 8fae38547f2f9a95c7d0deb3dc254c3f1b8fd083
git push origin v0.1.2

Please sign in to comment.