Skip to content

Commit

Permalink
Add print/write for PDBFile. It solves #8 and helps with #10
Browse files Browse the repository at this point in the history
  • Loading branch information
diegozea committed Apr 14, 2016
1 parent 1d0cc7e commit 1427ebb
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 0 deletions.
90 changes: 90 additions & 0 deletions src/PDB/PDBParser.jl
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,93 @@ function parse(io::Union{IO, ASCIIString}, ::Type{PDBFile}; chain::ASCIIString =
end
_generate_residues(residue_dict)
end

# Print PDB
# =========

# ATOM & HETATM
# COLUMNS DATA TYPE CONTENTS
# --------------------------------------------------------------------------------
# 1 - 6 Record name "ATOM "
# 7 - 11 Integer Atom serial number.
# 13 - 16 Atom Atom name.
# 17 Character Alternate location indicator.
# 18 - 20 Residue name Residue name.
# 22 Character Chain identifier.
# 23 - 26 Integer Residue sequence number.
# 27 AChar Code for insertion of residues.
# 31 - 38 Real(8.3) Orthogonal coordinates for X in Angstroms.
# 39 - 46 Real(8.3) Orthogonal coordinates for Y in Angstroms.
# 47 - 54 Real(8.3) Orthogonal coordinates for Z in Angstroms.
# 55 - 60 Real(6.2) Occupancy.
# 61 - 66 Real(6.2) Temperature factor (Default = 0.0).
# 73 - 76 LString(4) Segment identifier, left-justified.
# 77 - 78 LString(2) Element symbol, right-justified.
# 79 - 80 LString(2) Charge on the atom.
# Example:
# 1 2 3 4 5 6 7 8
# 12345678901234567890123456789012345678901234567890123456789012345678901234567890
# ATOM 145 N VAL A 25 32.433 16.336 57.540 1.00 11.92 A1 N
# ATOM 146 CA VAL A 25 31.132 16.439 58.160 1.00 11.85 A1 C
# ATOM 147 C VAL A 25 30.447 15.105 58.363 1.00 12.34 A1 C
# ATOM 148 O VAL A 25 29.520 15.059 59.174 1.00 15.65 A1 O
# ATOM 149 CB AVAL A 25 30.385 17.437 57.230 0.28 13.88 A1 C
# ATOM 150 CB BVAL A 25 30.166 17.399 57.373 0.72 15.41 A1 C
# ATOM 151 CG1AVAL A 25 28.870 17.401 57.336 0.28 12.64 A1 C
# ATOM 152 CG1BVAL A 25 30.805 18.788 57.449 0.72 15.11 A1 C
# ATOM 153 CG2AVAL A 25 30.835 18.826 57.661 0.28 13.58 A1 C
# ATOM 154 CG2BVAL A 25 29.909 16.996 55.922 0.72 13.25 A1 C
#
# HETATM 1357 MG MG 168 4.669 34.118 19.123 1.00 3.16 MG2+
# HETATM 3835 FE HEM 1 17.140 3.115 15.066 1.00 14.14 FE3+

const _Format_PDB_ATOM = FormatExpr(
# 1 2 3 4 5 6 7 8
# 12345678901234567890123456789012345678901234567890123456789012345678901234567890
# > <> < > <|> < |> <| > <> <> <> <> < > <><><
"{:<6}{:>5d} {:<4}{:>1}{:>3} {:>1}{:>4}{:>1} {:>8.3f}{:>8.3f}{:>8.3f}{:>6.2f}{:>6.2f} {:<4}{:>2}{:>2}\n"
)

function print(io::IO, res::PDBResidue, format::Type{PDBFile}, atom_index::Int, serial_number::Int)
number = match(r"(\d+)(\D?)", res.id.number)
atomname = res.atoms[atom_index].atom
printfmt(io, _Format_PDB_ATOM,
res.id.group,
serial_number,
length(atomname) <= 3 ? string(" ", atomname) : atomname, # It works with NACCESS
" ",
res.id.name,
res.id.chain,
number[1],
number[2],
res.atoms[atom_index].coordinates.x,
res.atoms[atom_index].coordinates.y,
res.atoms[atom_index].coordinates.z,
res.atoms[atom_index].occupancy,
res.atoms[atom_index].B,
" ",
res.atoms[atom_index].element,
" ")
serial_number + 1
end

function print(io::IO, res::PDBResidue, format::Type{PDBFile}, start::Int=1)
next = start
for i in 1:length(res.atoms)
next = print(io, res, format, i, next)
end
nothing
end

function print(io::IO, reslist::AbstractVector{PDBResidue}, format::Type{PDBFile}, start::Int=1)
next = start
for res in reslist
for i in 1:length(res.atoms)
next = print(io, res, format, i, next)
end
end
nothing
end

print(reslist::AbstractVector{PDBResidue}, format::Type{PDBFile}) = print(STDOUT, reslist, format)
print(res::PDBResidue, format::Type{PDBFile}) = print(STDOUT, res, format)
16 changes: 16 additions & 0 deletions test/pdb.jl
Original file line number Diff line number Diff line change
Expand Up @@ -236,3 +236,19 @@ RESTful PDB Interface

@test getpdbdescription("4HHB")["resolution"] == "1.74"
@test_throws KeyError getpdbdescription("104D")["resolution"] # NMR

print("""
Write PDB files
===============
""")

let code = "2VQC", io = IOBuffer()
pdb = read(txt(code), PDBFile)
print(io, pdb, PDBFile)
printed = split(takebuf_string(io), '\n')

@test length(printed) == 608 # Only ATOM & HETATM + 1 because the trailing \n
@test printed[1] == "ATOM 1 N THR A 4 2.431 19.617 6.520 1.00 24.37 N "
@test printed[607] == "HETATM 607 O HOH A2025 13.807 38.993 2.453 1.00 33.00 O "
end

0 comments on commit 1427ebb

Please sign in to comment.