Skip to content

Commit

Permalink
Properly integrate XSF
Browse files Browse the repository at this point in the history
  • Loading branch information
mfherbst committed Jul 16, 2023
1 parent 8db2ec1 commit 425cf8f
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 21 deletions.
1 change: 1 addition & 0 deletions docs/src/file_formats.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ The following list all currently available parsers, in the order they are tried

```@docs
AtomsIO.ExtxyzParser
AtomsIO.XcrysdenstructureformatParser
AtomsIO.ChemfilesParser
AtomsIOPython.AseParser
```
2 changes: 2 additions & 0 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ AtomsIO currently integrates with

- [Chemfiles](https://github.com/chemfiles/Chemfiles.jl)
- [ExtXYZ](https://github.com/libAtoms/ExtXYZ.jl)
- [XCrySDenStructureFormat](https://github.com/azadoks/XCrySDenStructureFormat.jl)
- [ASEconvert](https://github.com/mfherbst/ASEconvert.jl)
(respectively [ASE](https://wiki.fysik.dtu.dk/ase/))

Expand All @@ -16,6 +17,7 @@ and supports all file formats any of these packages support
- [Quantum Espresso](https://www.quantum-espresso.org/Doc/INPUT_PW.html) / [ABINIT](https://docs.abinit.org/variables/) / [VASP](https://www.vasp.at/wiki/) input files
- ASE / [Gromacs](http://manual.gromacs.org/archive/5.0.7/online/trj.html) / [LAMMPS](https://lammps.sandia.gov/doc/dump.html) / [Amber](http://ambermd.org/netcdf/nctraj.xhtml) trajectory files
- [XYZ](https://openbabel.org/wiki/XYZ) and [extxyz](https://github.com/libAtoms/extxyz#extended-xyz-specification-and-parsing-tools) files
- [XSF](http://www.xcrysden.org/doc/XSF.html) (XCrySDen) atomic structure files.

For more details see [Saving and loading files](@ref) and [File Formats](@ref).

Expand Down
4 changes: 3 additions & 1 deletion src/AtomsIO.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import PeriodicTable
include("parser.jl")
include("chemfiles.jl")
include("extxyz.jl")
include("xsf.jl")
include("saveload.jl")

export load_system, save_system, load_trajectory, save_trajectory
export AbstractParser, ChemfilesParser, ExtxyzParser
export AbstractParser
export ChemfilesParser, ExtxyzParser, XcrysdenstructureformatParser
end
4 changes: 3 additions & 1 deletion src/saveload.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
# *breaking change* (as it alters the behaviour of AtomsIO.load_system).
# Moreover since not all users will want to rely on Python dependencies, it is
# crucial that the python packages are only *appended* to this list.
const DEFAULT_PARSER_ORDER = AbstractParser[ExtxyzParser(), ChemfilesParser()]
const DEFAULT_PARSER_ORDER = AbstractParser[
ExtxyzParser(), XcrysdenstructureformatParser(), ChemfilesParser(),
]

function determine_parser(file; save=false, trajectory=false)
idx_parser = findfirst(DEFAULT_PARSER_ORDER) do parser
Expand Down
46 changes: 29 additions & 17 deletions src/xsf.jl
Original file line number Diff line number Diff line change
@@ -1,43 +1,55 @@
import XCrySDenStructureFormat as XSF

"""
Parse or write file using [XSF](https://github.com/azadoks/XCrySDenStructureFormat.jl)
Parse or write file using [XCrySDenStructureFormat](https://github.com/azadoks/XCrySDenStructureFormat.jl).
Supported formats:
- [XSF](http://www.xcrysden.org/doc/XSF.html)
- [XSF](http://www.xcrysden.org/doc/XSF.html) and [AXSF](XCrySDenStructureFormat)
atomic structure files. These are the files typically used by the
[XCrySDen](http://www.xcrysden.org/) visualisation program.
"""
struct XsfParser <: AbstractParser end
struct XcrysdenstructureformatParser <: AbstractParser end

function supports_parsing(::XsfParser, file; save, trajectory)
function supports_parsing(::XcrysdenstructureformatParser, file; save, trajectory)

Check warning on line 13 in src/xsf.jl

View check run for this annotation

Codecov / codecov/patch

src/xsf.jl#L13

Added line #L13 was not covered by tests
_, ext = splitext(file)
ext in (".xsf", ".axsf")
end

function load_system(::XsfParser, file::AbstractString, index=nothing)
if isnothing(index)
frames = XSF.load_xsf(file)
function load_system(::XcrysdenstructureformatParser, file::AbstractString, index=nothing)
if !isnothing(index)
return XSF.load_xsf(file)[index]

Check warning on line 20 in src/xsf.jl

View check run for this annotation

Codecov / codecov/patch

src/xsf.jl#L18-L20

Added lines #L18 - L20 were not covered by tests
end


frames = XSF.load_xsf(file)
if !(frames isa AbstractVector)

Check warning on line 25 in src/xsf.jl

View check run for this annotation

Codecov / codecov/patch

src/xsf.jl#L24-L25

Added lines #L24 - L25 were not covered by tests
# load_xsf Returns plain structure in case only a single structure in the file
return frames

Check warning on line 27 in src/xsf.jl

View check run for this annotation

Codecov / codecov/patch

src/xsf.jl#L27

Added line #L27 was not covered by tests
else
isempty(frames) && error(
"XSF returned no frames. Check the passed file is a valid (a)xsf file."
)
return last(frames)
else
return XSF.load_xsf(file)[index]
end
end

function save_system(::XsfParser, file::AbstractString, system::AbstractSystem)
function save_system(::XcrysdenstructureformatParser,

Check warning on line 36 in src/xsf.jl

View check run for this annotation

Codecov / codecov/patch

src/xsf.jl#L36

Added line #L36 was not covered by tests
file::AbstractString, system::AbstractSystem)
XSF.save_xsf(file, system)
end

function load_trajectory(::XsfParser, file::AbstractString)
XSF.load_xsf(file)
end

function save_system(::XsfParser, file::AbstractString, system::AbstractSystem)
XSF.save_xsf(file, system)
function load_trajectory(::XcrysdenstructureformatParser, file::AbstractString)

Check warning on line 41 in src/xsf.jl

View check run for this annotation

Codecov / codecov/patch

src/xsf.jl#L41

Added line #L41 was not covered by tests
# load_xsf Returns plain structure in case only a single structure in the file,
# so we need to re-wrap to keep a consistent interface.
ret = XSF.load_xsf(file)
if !(ret isa AbstractVector)
return [ret]

Check warning on line 46 in src/xsf.jl

View check run for this annotation

Codecov / codecov/patch

src/xsf.jl#L44-L46

Added lines #L44 - L46 were not covered by tests
else
return ret

Check warning on line 48 in src/xsf.jl

View check run for this annotation

Codecov / codecov/patch

src/xsf.jl#L48

Added line #L48 was not covered by tests
end
end

function save_trajectory(::XsfParser, file::AbstractString,
function save_trajectory(::XcrysdenstructureformatParser, file::AbstractString,

Check warning on line 52 in src/xsf.jl

View check run for this annotation

Codecov / codecov/patch

src/xsf.jl#L52

Added line #L52 was not covered by tests
systems::AbstractVector{<:AbstractSystem})
XSF.save_xsf(file, systems)
end
10 changes: 8 additions & 2 deletions test/failed_files.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ using LinearAlgebra

# Tests parsing files, where previously users reported problems
@testset "Failed files" begin
@testset "Empty XYZ" begin
@test_throws "ExtXYZ returned no frames." load_system("files/empty.xyz")
end

@testset "XYZ from Lammps" begin
@test_throws "ExtXYZ returned no frames." load_system("files/lammps.xyz")
end

@testset "CIF Graphene P6/mmm" begin
parsed = load_system("files/graphene.cif")
reduced = reduce(hcat, bounding_box(parsed))
Expand All @@ -15,7 +23,5 @@ using LinearAlgebra
@test atomic_symbol(parsed) == [:C1, :C2, :C3, :C4]
@test atomic_number(parsed) == [6, 6, 6, 6]
@test parsed[:name] == "Graphene"


end
end
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ if GROUP == "Core"
@testset "AtomsIO.jl" begin
include("chemfiles.jl")
include("extxyz.jl")
include("xsf.jl")
include("failed_files.jl")
# For the comparison tests (also between Chemfiles and ExtXYZ and other
# non-python libraries) see the AtomsIOPython subproject
Expand Down
6 changes: 6 additions & 0 deletions test/xsf.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ using Test
using AtomsBaseTesting

@testset "XSF system write / read" begin
XsfParser = AtomsIO.XcrysdenstructureformatParser

system = make_test_system().system
mktempdir() do d
outfile = joinpath(d, "output.xsf")
Expand All @@ -13,6 +15,8 @@ using AtomsBaseTesting
end

@testset "XSF trajectory write/read" begin
XsfParser = AtomsIO.XcrysdenstructureformatParser

systems = [make_test_system().system for _ in 1:3]
mktempdir() do d
outfile = joinpath(d, "output.axsf")
Expand All @@ -28,6 +32,8 @@ end

@testset "ExtXYZ supports_parsing" begin
import AtomsIO: supports_parsing
XsfParser = AtomsIO.XcrysdenstructureformatParser

prefix = "test"
save = trajectory = true
@test supports_parsing(XsfParser(), prefix * ".xsf"; save, trajectory)
Expand Down

0 comments on commit 425cf8f

Please sign in to comment.