{-# LANGUAGE OverloadedStrings #-} -- | Simple input/output wrappers taking filenames, and handling compression. module Bio.PDB.IO(parse, write, PDBWritable()) where import qualified Control.Exception(catch) import Control.Exception.Base(SomeException) import System.IO hiding(writeFile, FilePath) import Prelude hiding(String,writeFile) import Bio.PDB.EventParser.PDBParsingAbstractions import Bio.PDB.Structure.List as L import qualified Bio.PDB.StructurePrinter as PDBSP import Bio.PDB.StructurePrinter(PDBWritable()) import Control.Monad(when) import Bio.PDB.EventParser.PDBEvents(PDBEvent(PDBParseError, PDBIgnoredLine)) --import qualified Bio.PDB.EventParser.PDBEventPrinter as PDBEventPrinter import qualified Bio.PDB.StructureBuilder(parse) import qualified Bio.PDB.Structure import qualified Data.ByteString.Char8 as BS import Bio.PDB.IO.OpenAnyFile import Control.DeepSeq -- | Type alias. type String = BS.ByteString -- Until I get a newer version of Control.DeepSeq: -- | Alias to a function present in newer versions of 'deepseq' library. force x = x `deepseq` x -- | Parse a .pdb file and return `Bio.PDB.Structure.Structure`. parse :: FilePath -> IO (Maybe Bio.PDB.Structure.Structure) parse filename = do input <- Bio.PDB.IO.OpenAnyFile.readFile filename do (structure, errs) <- return $ Bio.PDB.StructureBuilder.parse filename input mapM_ (showError filename) (L.toList errs) structure `deepseq` return $ Just structure `Control.Exception.catch` exceptionHandler filename -- | Default exception handler that for `IO (Maybe a)` just prints nice error message to stderr, and returns Nothing exceptionHandler :: FilePath -> SomeException -> IO (Maybe a) exceptionHandler filename e = do printError [BS.pack filename, ":", BS.pack $ show e] return Nothing -- | Prints a catenated list of ByteStrings to stderr. (Convenience function.) printError msg = BS.hPutStrLn System.IO.stderr $ BS.concat msg -- | Show error message from `PDBParser`. showError filename (PDBParseError line_no col_no msg) = printError [BS.pack filename, ":", BS.pack $ show line_no, ":", BS.pack $ show col_no, "\t", msg] showError filename (PDBIgnoredLine line) = printError [BS.pack filename, ": IGNORED ", line] -- | Write structure to a .pdb file. write :: PDBWritable a => a -> FilePath -> IO () write structure fname = writeFile fname $ \h -> PDBSP.write h structure