module Bio.PDB.StructurePrinter(write, PDBWritable()) where
import Prelude hiding(print)
import Control.Monad(mapM_)
import System.IO(Handle)
import Data.ByteString.Char8 as BS
import Bio.PDB.Structure
import Bio.PDB.Iterable
import Bio.PDB.Structure.List as L
import Bio.PDB.EventParser.PDBEventPrinter as PR
import Bio.PDB.EventParser.PDBEvents
type PDBEventS = [PDBEvent] -> [PDBEvent]
write :: PDBWritable a => Handle -> a -> IO ()
write handle structure = mapM_ (PR.print handle) (pdbEvents structure)
class PDBWritable a where
pdbEvents :: a -> [PDBEvent]
pdbEvents = flip pdbEventS []
pdbEventS :: a -> PDBEventS
instance PDBWritable Structure
where
pdbEvents = structureEvents
pdbEventS = error "Structure is closed by definition cannot have continuation!"
instance PDBWritable Model
where
pdbEventS = modelEvents
instance PDBWritable Chain
where
pdbEventS = chainEvents
instance PDBWritable Residue
where
pdbEventS = residueEvents blankChain
instance PDBWritable Atom
where
pdbEventS = atomEvents blankChain blankResidue
blankChain :: Chain
blankChain = Chain { chainId = ' '
, residues = L.empty }
blankResidue :: Residue
blankResidue = Residue { resName = "UNK"
, resSeq = 0
, insCode = ' '
, atoms = L.empty }
structureEvents :: Structure -> [PDBEvent]
structureEvents s = itfoldr modelEvents [END] s
modelEvents :: Model -> PDBEventS
modelEvents m cont = start:main (ENDMDL : cont)
where
start = MODEL $ modelId m
main c = itfoldr chainEvents c m
chainEvents :: Chain -> PDBEventS
chainEvents ch c = itfoldr (residueEvents ch) (ter:c) ch
where
ter = TER { num = atSer + 1 ,
resname = lastResName ,
chain = chainId ch ,
resid = lastResSeq ,
insCode = lastInsCode }
Atom { atSerial = atSer } = L.last ats
Residue { resName = lastResName,
resSeq = lastResSeq ,
insCode = lastInsCode,
atoms = ats
} = L.last . Bio.PDB.Structure.residues $ ch
residueEvents :: Chain -> Residue -> PDBEventS
residueEvents ch r c = itfoldr (atomEvents ch r) c r
atomEvents :: Chain -> Residue -> Atom -> PDBEventS
atomEvents (Chain { chainId = chid }
) (Residue { resName = rtype,
resSeq = rid,
insCode = rins
}
) (Atom { atName = atName,
atSerial = atSer,
coord = coord,
bFactor = bf,
occupancy = occ,
element = e,
segid = sid,
charge = ch,
hetatm = isHet
}) c = ATOM { no = atSer,
atomtype = atName,
restype = rtype,
chain = chid,
resid = rid,
resins = rins,
altloc = ' ',
coords = coord,
occupancy = occ,
bfactor = bf,
segid = sid,
elt = e,
charge = ch,
hetatm = isHet
} : c