mmtf 0.1.2.0 → 0.1.3.0
raw patch · 7 files changed
+342/−156 lines, 7 filesdep +arraydep +deepseqPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: array, deepseq
API changes (from Hackage documentation)
+ Bio.MMTF: M44 :: Float -> Float -> Float -> Float -> Float -> Float -> Float -> Float -> Float -> Float -> Float -> Float -> Float -> Float -> Float -> Float -> M44
+ Bio.MMTF: data M44
+ Bio.MMTF: type IArray a = Array Int a
+ Bio.MMTF.Structure: Atom :: Text -> Text -> (Float, Float, Float) -> Int -> Float -> Float -> Atom
+ Bio.MMTF.Structure: Bond :: Int -> Int -> Int -> Bond
+ Bio.MMTF.Structure: Chain :: Text -> Array Int Residue -> Chain
+ Bio.MMTF.Structure: Model :: Array Int Chain -> Model
+ Bio.MMTF.Structure: Residue :: Text -> Array Int Atom -> Array Int Bond -> SecondaryStructure -> Residue
+ Bio.MMTF.Structure: [atomCoords] :: Atom -> (Float, Float, Float)
+ Bio.MMTF.Structure: [atomElement] :: Atom -> Text
+ Bio.MMTF.Structure: [atomName] :: Atom -> Text
+ Bio.MMTF.Structure: [bFactor] :: Atom -> Float
+ Bio.MMTF.Structure: [bondEnd] :: Bond -> Int
+ Bio.MMTF.Structure: [bondOrder] :: Bond -> Int
+ Bio.MMTF.Structure: [bondStart] :: Bond -> Int
+ Bio.MMTF.Structure: [chainName] :: Chain -> Text
+ Bio.MMTF.Structure: [chainResidues] :: Chain -> Array Int Residue
+ Bio.MMTF.Structure: [formalCharge] :: Atom -> Int
+ Bio.MMTF.Structure: [modelChains] :: Model -> Array Int Chain
+ Bio.MMTF.Structure: [occupancy] :: Atom -> Float
+ Bio.MMTF.Structure: [resAtoms] :: Residue -> Array Int Atom
+ Bio.MMTF.Structure: [resBonds] :: Residue -> Array Int Bond
+ Bio.MMTF.Structure: [resName] :: Residue -> Text
+ Bio.MMTF.Structure: [resSecondary] :: Residue -> SecondaryStructure
+ Bio.MMTF.Structure: data Atom
+ Bio.MMTF.Structure: data Bond
+ Bio.MMTF.Structure: data Chain
+ Bio.MMTF.Structure: data Residue
+ Bio.MMTF.Structure: instance Control.DeepSeq.NFData Bio.MMTF.Structure.Atom
+ Bio.MMTF.Structure: instance Control.DeepSeq.NFData Bio.MMTF.Structure.Bond
+ Bio.MMTF.Structure: instance Control.DeepSeq.NFData Bio.MMTF.Structure.Chain
+ Bio.MMTF.Structure: instance Control.DeepSeq.NFData Bio.MMTF.Structure.Model
+ Bio.MMTF.Structure: instance Control.DeepSeq.NFData Bio.MMTF.Structure.Residue
+ Bio.MMTF.Structure: instance GHC.Classes.Eq Bio.MMTF.Structure.Atom
+ Bio.MMTF.Structure: instance GHC.Classes.Eq Bio.MMTF.Structure.Bond
+ Bio.MMTF.Structure: instance GHC.Classes.Eq Bio.MMTF.Structure.Chain
+ Bio.MMTF.Structure: instance GHC.Classes.Eq Bio.MMTF.Structure.Model
+ Bio.MMTF.Structure: instance GHC.Classes.Eq Bio.MMTF.Structure.Residue
+ Bio.MMTF.Structure: instance GHC.Generics.Generic Bio.MMTF.Structure.Atom
+ Bio.MMTF.Structure: instance GHC.Generics.Generic Bio.MMTF.Structure.Bond
+ Bio.MMTF.Structure: instance GHC.Generics.Generic Bio.MMTF.Structure.Chain
+ Bio.MMTF.Structure: instance GHC.Generics.Generic Bio.MMTF.Structure.Model
+ Bio.MMTF.Structure: instance GHC.Generics.Generic Bio.MMTF.Structure.Residue
+ Bio.MMTF.Structure: instance GHC.Show.Show Bio.MMTF.Structure.Atom
+ Bio.MMTF.Structure: instance GHC.Show.Show Bio.MMTF.Structure.Bond
+ Bio.MMTF.Structure: instance GHC.Show.Show Bio.MMTF.Structure.Chain
+ Bio.MMTF.Structure: instance GHC.Show.Show Bio.MMTF.Structure.Model
+ Bio.MMTF.Structure: instance GHC.Show.Show Bio.MMTF.Structure.Residue
+ Bio.MMTF.Structure: modelsOf :: MMTF -> Array Int Model
+ Bio.MMTF.Structure: newtype Model
- Bio.MMTF: Assembly :: ![Transform] -> !Text -> Assembly
+ Bio.MMTF: Assembly :: !IArray Transform -> !Text -> Assembly
- Bio.MMTF: AtomData :: ![Int32] -> ![Char] -> ![Float] -> ![Float] -> ![Float] -> ![Float] -> ![Float] -> AtomData
+ Bio.MMTF: AtomData :: !IArray Int32 -> !IArray Text -> !IArray Float -> !IArray Float -> !IArray Float -> !IArray Float -> !IArray Float -> AtomData
- Bio.MMTF: ChainData :: ![Int32] -> ![Text] -> ![Text] -> ChainData
+ Bio.MMTF: ChainData :: !IArray Int32 -> !IArray Text -> !IArray Text -> ChainData
- Bio.MMTF: Entity :: ![Int32] -> !Text -> !Text -> !Text -> Entity
+ Bio.MMTF: Entity :: !IArray Int32 -> !Text -> !Text -> !Text -> Entity
- Bio.MMTF: GroupData :: ![GroupType] -> ![Int32] -> ![Int32] -> ![SecondaryStructure] -> ![Char] -> ![Int32] -> GroupData
+ Bio.MMTF: GroupData :: !IArray GroupType -> !IArray Int32 -> !IArray Int32 -> !IArray SecondaryStructure -> !IArray Text -> !IArray Int32 -> GroupData
- Bio.MMTF: GroupType :: ![Int32] -> ![Text] -> ![Text] -> ![Int32] -> ![Int32] -> !Text -> !Char -> !Text -> GroupType
+ Bio.MMTF: GroupType :: !IArray Int32 -> !IArray Text -> !IArray Text -> !IArray (Int32, Int32) -> !IArray Int32 -> !Text -> !Char -> !Text -> GroupType
- Bio.MMTF: ModelData :: ![Int32] -> ModelData
+ Bio.MMTF: ModelData :: !IArray Int32 -> ModelData
- Bio.MMTF: StructureData :: !Text -> !Text -> !Text -> !Text -> !Int32 -> !Int32 -> !Int32 -> !Int32 -> !Int32 -> !Text -> !Maybe UnitCell -> ![[Float]] -> ![Assembly] -> ![Entity] -> !Maybe Float -> !Maybe Float -> !Maybe Float -> ![Text] -> ![Int32] -> ![Int8] -> StructureData
+ Bio.MMTF: StructureData :: !Text -> !Text -> !Text -> !Text -> !Int32 -> !Int32 -> !Int32 -> !Int32 -> !Int32 -> !Text -> !Maybe UnitCell -> !IArray M44 -> !IArray Assembly -> !IArray Entity -> !Maybe Float -> !Maybe Float -> !Maybe Float -> !IArray Text -> !IArray (Int32, Int32) -> !IArray Int8 -> StructureData
- Bio.MMTF: Transform :: ![Int32] -> ![Float] -> Transform
+ Bio.MMTF: Transform :: !IArray Int32 -> !M44 -> Transform
- Bio.MMTF: [altLocList] :: AtomData -> ![Char]
+ Bio.MMTF: [altLocList] :: AtomData -> !IArray Text
- Bio.MMTF: [atomIdList] :: AtomData -> ![Int32]
+ Bio.MMTF: [atomIdList] :: AtomData -> !IArray Int32
- Bio.MMTF: [bFactorList] :: AtomData -> ![Float]
+ Bio.MMTF: [bFactorList] :: AtomData -> !IArray Float
- Bio.MMTF: [bioAssemblyList] :: StructureData -> ![Assembly]
+ Bio.MMTF: [bioAssemblyList] :: StructureData -> !IArray Assembly
- Bio.MMTF: [bondAtomList] :: StructureData -> ![Int32]
+ Bio.MMTF: [bondAtomList] :: StructureData -> !IArray (Int32, Int32)
- Bio.MMTF: [bondOrderList] :: StructureData -> ![Int8]
+ Bio.MMTF: [bondOrderList] :: StructureData -> !IArray Int8
- Bio.MMTF: [chainIdList] :: ChainData -> ![Text]
+ Bio.MMTF: [chainIdList] :: ChainData -> !IArray Text
- Bio.MMTF: [chainIndexList] :: Transform -> ![Int32]
+ Bio.MMTF: [chainIndexList] :: Transform -> !IArray Int32
- Bio.MMTF: [chainNameList] :: ChainData -> ![Text]
+ Bio.MMTF: [chainNameList] :: ChainData -> !IArray Text
- Bio.MMTF: [chainsPerModel] :: ModelData -> ![Int32]
+ Bio.MMTF: [chainsPerModel] :: ModelData -> !IArray Int32
- Bio.MMTF: [entityChainIndexList] :: Entity -> ![Int32]
+ Bio.MMTF: [entityChainIndexList] :: Entity -> !IArray Int32
- Bio.MMTF: [entityList] :: StructureData -> ![Entity]
+ Bio.MMTF: [entityList] :: StructureData -> !IArray Entity
- Bio.MMTF: [experimentalMethods] :: StructureData -> ![Text]
+ Bio.MMTF: [experimentalMethods] :: StructureData -> !IArray Text
- Bio.MMTF: [groupIdList] :: GroupData -> ![Int32]
+ Bio.MMTF: [groupIdList] :: GroupData -> !IArray Int32
- Bio.MMTF: [groupList] :: GroupData -> ![GroupType]
+ Bio.MMTF: [groupList] :: GroupData -> !IArray GroupType
- Bio.MMTF: [groupTypeList] :: GroupData -> ![Int32]
+ Bio.MMTF: [groupTypeList] :: GroupData -> !IArray Int32
- Bio.MMTF: [groupsPerChain] :: ChainData -> ![Int32]
+ Bio.MMTF: [groupsPerChain] :: ChainData -> !IArray Int32
- Bio.MMTF: [gtAtomNameList] :: GroupType -> ![Text]
+ Bio.MMTF: [gtAtomNameList] :: GroupType -> !IArray Text
- Bio.MMTF: [gtBondAtomList] :: GroupType -> ![Int32]
+ Bio.MMTF: [gtBondAtomList] :: GroupType -> !IArray (Int32, Int32)
- Bio.MMTF: [gtBondOrderList] :: GroupType -> ![Int32]
+ Bio.MMTF: [gtBondOrderList] :: GroupType -> !IArray Int32
- Bio.MMTF: [gtElementList] :: GroupType -> ![Text]
+ Bio.MMTF: [gtElementList] :: GroupType -> !IArray Text
- Bio.MMTF: [gtFormalChargeList] :: GroupType -> ![Int32]
+ Bio.MMTF: [gtFormalChargeList] :: GroupType -> !IArray Int32
- Bio.MMTF: [insCodeList] :: GroupData -> ![Char]
+ Bio.MMTF: [insCodeList] :: GroupData -> !IArray Text
- Bio.MMTF: [matrix] :: Transform -> ![Float]
+ Bio.MMTF: [matrix] :: Transform -> !M44
- Bio.MMTF: [ncsOperatorList] :: StructureData -> ![[Float]]
+ Bio.MMTF: [ncsOperatorList] :: StructureData -> !IArray M44
- Bio.MMTF: [occupancyList] :: AtomData -> ![Float]
+ Bio.MMTF: [occupancyList] :: AtomData -> !IArray Float
- Bio.MMTF: [secStructList] :: GroupData -> ![SecondaryStructure]
+ Bio.MMTF: [secStructList] :: GroupData -> !IArray SecondaryStructure
- Bio.MMTF: [sequenceIndexList] :: GroupData -> ![Int32]
+ Bio.MMTF: [sequenceIndexList] :: GroupData -> !IArray Int32
- Bio.MMTF: [transformList] :: Assembly -> ![Transform]
+ Bio.MMTF: [transformList] :: Assembly -> !IArray Transform
- Bio.MMTF: [xCoordList] :: AtomData -> ![Float]
+ Bio.MMTF: [xCoordList] :: AtomData -> !IArray Float
- Bio.MMTF: [yCoordList] :: AtomData -> ![Float]
+ Bio.MMTF: [yCoordList] :: AtomData -> !IArray Float
- Bio.MMTF: [zCoordList] :: AtomData -> ![Float]
+ Bio.MMTF: [zCoordList] :: AtomData -> !IArray Float
Files
- mmtf.cabal +6/−2
- src/Bio/MMTF/Decode.hs +73/−50
- src/Bio/MMTF/Decode/Codec.hs +8/−0
- src/Bio/MMTF/Decode/MessagePack.hs +34/−32
- src/Bio/MMTF/Structure.hs +104/−0
- src/Bio/MMTF/Type.hs +112/−68
- test/Spec.hs +5/−4
mmtf.cabal view
@@ -1,5 +1,5 @@ name: mmtf-version: 0.1.2.0+version: 0.1.3.0 synopsis: Macromolecular Transmission Format implementation description: Haskell implementation of MMTF biological structure format. homepage: https://github.com/zmactep/mmtf#readme@@ -7,7 +7,7 @@ license-file: LICENSE author: Pavel Yakovlev maintainer: pavel@yakovlev.me-copyright: (c) 2017, Pavel Yakovlev+copyright: (c) 2017—2019, Pavel Yakovlev category: Bioinformatics build-type: Simple extra-source-files: README.md@@ -16,6 +16,7 @@ library hs-source-dirs: src exposed-modules: Bio.MMTF+ , Bio.MMTF.Structure other-modules: Bio.MMTF.Type , Bio.MMTF.MessagePack , Bio.MMTF.Decode@@ -28,6 +29,8 @@ , binary >= 0.8.3.0 && < 1.0 , containers >= 0.5.7.1 && < 0.7 , http-conduit >= 2.3 && < 2.4+ , array >= 0.5 && < 0.6+ , deepseq >= 1.4 && < 1.5 default-language: Haskell2010 ghc-options: -Wall @@ -52,6 +55,7 @@ , binary , containers , http-conduit+ , array ghc-options: -threaded -rtsopts -with-rtsopts=-N default-language: Haskell2010
src/Bio/MMTF/Decode.hs view
@@ -10,19 +10,21 @@ import Data.ByteString.Lazy (empty) import Data.Map.Strict (Map) import Data.MessagePack (Object)-import Data.Text (Text)+import Data.Text (Text, pack)+import Data.Char (ord)+import Data.Array (listArray) -- | Parses format data from ObjectMap -- formatData :: Monad m => Map Text Object -> m FormatData-formatData mp = do v <- atP mp "mmtfVersion" asStr+formatData mp = do v <- atP mp "mmtfVersion" asStr p <- atP mp "mmtfProducer" asStr pure $ FormatData v p -- | Parses model data from ObjectMap -- modelData :: Monad m => Map Text Object -> m ModelData-modelData mp = ModelData <$> atP mp "chainsPerModel" asIntList+modelData mp = ModelData . l2a <$> atP mp "chainsPerModel" asIntList -- | Parses chain data from ObjectMap --@@ -30,83 +32,85 @@ chainData mp = do gpc <- atP mp "groupsPerChain" asIntList cil <- codec5 . parseBinary <$> atP mp "chainIdList" asBinary cnl <- codec5 . parseBinary <$> atPMD mp "chainNameList" asBinary empty- pure $ ChainData gpc cil cnl+ pure $ ChainData (l2a gpc) (l2a cil) (l2a cnl) -- | Parses atom data from ObjectMap -- atomData :: Monad m => Map Text Object -> m AtomData-atomData mp = do ail' <- codec8 . parseBinary <$> atPMD mp "atomIdList" asBinary empty- all' <- codec6 . parseBinary <$> atPMD mp "altLocList" asBinary empty- bfl' <- codec10 . parseBinary <$> atPMD mp "bFactorList" asBinary empty- xcl' <- codec10 . parseBinary <$> atP mp "xCoordList" asBinary- ycl' <- codec10 . parseBinary <$> atP mp "yCoordList" asBinary- zcl' <- codec10 . parseBinary <$> atP mp "zCoordList" asBinary- ol' <- codec9 . parseBinary <$> atPMD mp "occupancyList" asBinary empty- pure $ AtomData ail' all' bfl' xcl' ycl' zcl' ol'+atomData mp = do ail' <- codec8 . parseBinary <$> atPMD mp "atomIdList" asBinary empty+ all' <- c2s . codec6 . parseBinary <$> atPMD mp "altLocList" asBinary empty+ bfl' <- codec10 . parseBinary <$> atPMD mp "bFactorList" asBinary empty+ xcl' <- codec10 . parseBinary <$> atP mp "xCoordList" asBinary+ ycl' <- codec10 . parseBinary <$> atP mp "yCoordList" asBinary+ zcl' <- codec10 . parseBinary <$> atP mp "zCoordList" asBinary+ ol' <- codec9 . parseBinary <$> atPMD mp "occupancyList" asBinary empty+ pure $ AtomData (l2a ail') (l2a all') (l2a bfl') (l2a xcl') (l2a ycl') (l2a zcl') (l2a ol') -- | Parses group data from ObjectMap -- groupData :: Monad m => Map Text Object -> m GroupData-groupData mp = do gl' <- atP mp "groupList" asObjectList >>= traverse (transformObjectMap >=> groupType)+groupData mp = do gl' <- atP mp "groupList" asObjectList >>= traverse (transformObjectMap >=> groupType) gtl' <- codec4 . parseBinary <$> atP mp "groupTypeList" asBinary gil' <- codec8 . parseBinary <$> atP mp "groupIdList" asBinary ssl' <- fmap ssDec . codec2 . parseBinary <$> atPMD mp "secStructList" asBinary empty- icl' <- codec6 . parseBinary <$> atPMD mp "insCodeList" asBinary empty+ icl' <- c2s . codec6 . parseBinary <$> atPMD mp "insCodeList" asBinary empty sil' <- codec8 . parseBinary <$> atPMD mp "sequenceIndexList" asBinary empty- pure $ GroupData gl' gtl' gil' ssl' icl' sil'+ pure $ GroupData (l2a gl') (l2a gtl') (l2a gil') (l2a ssl') (l2a icl') (l2a sil') -- | Parses group type from ObjectMap -- groupType :: Monad m => Map Text Object -> m GroupType-groupType mp = do fcl' <- atP mp "formalChargeList" asIntList- anl' <- atP mp "atomNameList" asStrList- el' <- atP mp "elementList" asStrList- bal' <- atP mp "bondAtomList" asIntList- bol' <- atP mp "bondOrderList" asIntList- gn' <- atP mp "groupName" asStr- slc' <- atP mp "singleLetterCode" asChar- cct' <- atP mp "chemCompType" asStr- pure $ GroupType fcl' anl' el' bal' bol' gn' slc' cct'+groupType mp = do fcl' <- atP mp "formalChargeList" asIntList+ anl' <- atP mp "atomNameList" asStrList+ el' <- atP mp "elementList" asStrList+ bal' <- l2pl <$> atP mp "bondAtomList" asIntList+ bol' <- atP mp "bondOrderList" asIntList+ gn' <- atP mp "groupName" asStr+ slc' <- atP mp "singleLetterCode" asChar+ cct' <- atP mp "chemCompType" asStr+ pure $ GroupType (l2a fcl') (l2a anl') (l2a el') (l2a bal') (l2a bol') gn' slc' cct' -- | Parses structure data from ObjectMap -- structureData :: Monad m => Map Text Object -> m StructureData-structureData mp = do ttl' <- atPMD mp "title" asStr ""- sid' <- atPMD mp "structureId" asStr ""- dd' <- atPMD mp "depositionDate" asStr ""- rd' <- atPMD mp "releaseDate" asStr ""- nb' <- atP mp "numBonds" asInt- na' <- atP mp "numAtoms" asInt- ng' <- atP mp "numGroups" asInt- nc' <- atP mp "numChains" asInt- nm' <- atP mp "numModels" asInt- sg' <- atPMD mp "spaceGroup" asStr ""- uc' <- (>>= ucDec) <$> atPM mp "unitCell" asFloatList- nol' <- (>>= asFloatList) <$> atPMD mp "ncsOperatorList" asObjectList []- bal' <- atPMD mp "bioAssemblyList" asObjectList [] >>= traverse (transformObjectMap >=> bioAssembly)- el' <- atPMD mp "entityList" asObjectList [] >>= traverse (transformObjectMap >=> entity)- res' <- atPM mp "resolution" asFloat- rf' <- atPM mp "rFree" asFloat- rw' <- atPM mp "rWork" asFloat- em' <- atPMD mp "experimentalMethods" asStrList []- btl' <- codec4 . parseBinary <$> atPMD mp "bondAtomList" asBinary empty- bol' <- codec2 . parseBinary <$> atPMD mp "bondOrderList" asBinary empty- pure $ StructureData ttl' sid' dd' rd' nb' na' ng' nc' nm' sg' uc' nol'- bal' el' res' rf' rw' em' btl' bol'+structureData mp = do ttl' <- atPMD mp "title" asStr ""+ sid' <- atPMD mp "structureId" asStr ""+ dd' <- atPMD mp "depositionDate" asStr ""+ rd' <- atPMD mp "releaseDate" asStr ""+ nb' <- atP mp "numBonds" asInt+ na' <- atP mp "numAtoms" asInt+ ng' <- atP mp "numGroups" asInt+ nc' <- atP mp "numChains" asInt+ nm' <- atP mp "numModels" asInt+ sg' <- atPMD mp "spaceGroup" asStr ""+ uc' <- (>>= ucDec) <$> atPM mp "unitCell" asFloatList+ nol' <- m44Dec <$> atPMD mp "ncsOperatorList" asFloatList []+ bal' <- atPMD mp "bioAssemblyList" asObjectList [] >>= traverse (transformObjectMap >=> bioAssembly)+ el' <- atPMD mp "entityList" asObjectList [] >>= traverse (transformObjectMap >=> entity)+ res' <- atPM mp "resolution" asFloat+ rf' <- atPM mp "rFree" asFloat+ rw' <- atPM mp "rWork" asFloat+ em' <- atPMD mp "experimentalMethods" asStrList []+ btl' <- l2pl . codec4 . parseBinary <$> atPMD mp "bondAtomList" asBinary empty+ bol' <- codec2 . parseBinary <$> atPMD mp "bondOrderList" asBinary empty+ pure $ StructureData ttl' sid' dd' rd' nb' na'+ ng' nc' nm' sg' uc' (l2a nol')+ (l2a bal') (l2a el') res' rf'+ rw' (l2a em') (l2a btl') (l2a bol') -- | Parses bio assembly data from ObjectMap -- bioAssembly :: Monad m => Map Text Object -> m Assembly bioAssembly mp = do nme' <- atP mp "name" asStr tlt' <- atP mp "transformList" asObjectList >>= traverse (transformObjectMap >=> transform)- pure $ Assembly tlt' nme'+ pure $ Assembly (l2a tlt') nme' -- | Parses transform data from ObjectMap -- transform :: Monad m => Map Text Object -> m Transform transform mp = do cil' <- atP mp "chainIndexList" asIntList- mtx' <- atP mp "matrix" asFloatList- pure $ Transform cil' mtx'+ mtx' <- atP mp "matrix" asFloatList >>= m44Dec+ pure $ Transform (l2a cil') mtx' -- | Parses entity data from ObjectMap --@@ -115,4 +119,23 @@ dsc' <- atP mp "description" asStr tpe' <- atP mp "type" asStr sqc' <- atP mp "sequence" asStr- pure $ Entity cil' dsc' tpe' sqc'+ pure $ Entity (l2a cil') dsc' tpe' sqc'++-- | Converts list of chars to list of one-sized+-- (or zero-sized in case of zero) strings+c2s :: [Char] -> [Text]+c2s [] = []+c2s (x:xs) | ord x == 0 = "":c2s xs+ | otherwise = (pack [x]):c2s xs++-- | Converst list to an array+--+l2a :: [a] -> IArray a+l2a lst = listArray (0, length lst - 1) lst++-- | List to list of pairs+--+l2pl :: [a] -> [(a, a)]+l2pl [] = []+l2pl (x:y:xs) = (x,y) : l2pl xs+l2pl _ = error "Cannot convert a list of odd length to a list of pairs"
src/Bio/MMTF/Decode/Codec.hs view
@@ -23,6 +23,7 @@ , binaryParam :: !Int32 , binaryData :: !ByteString }+ deriving Show -- | Parse useless header for binary data --@@ -162,3 +163,10 @@ ucDec :: Monad m => [Float] -> m UnitCell ucDec [a,b,c,d,e,f] = pure $ UnitCell a b c d e f ucDec _ = fail "Wrong list format for unit cell"++m44Dec :: Monad m => [Float] -> m M44+m44Dec [ a11, a12, a13, a14+ , a21, a22, a23, a24+ , a31, a32, a33, a34+ , a41, a42, a43, a44] = pure $ M44 a11 a12 a13 a14 a21 a22 a23 a24 a31 a32 a33 a34 a41 a42 a43 a44+m44Dec _ = fail "Wrong list format for 4x4 transformation matrix"
src/Bio/MMTF/Decode/MessagePack.hs view
@@ -4,6 +4,7 @@ import Data.Map.Strict (Map, fromList) import qualified Data.Map.Strict as M (lookup) import Data.MessagePack+import Data.Monoid ((<>)) import Data.Text (Text) import qualified Data.Text as T (unpack) @@ -14,54 +15,55 @@ in fromList <$> traverse mkPair kv transformObjectMap _ = fail "Wrong MessagePack MMTF format" -atP :: Monad m => Map Text Object -> Text -> (Object -> m a) -> m a+atP :: Monad m => Map Text Object -> Text -> (Text -> Object -> m a) -> m a atP m k conv = case M.lookup k m of- Just x -> conv x+ Just x -> conv k x Nothing -> fail $ "Required field '" ++ uk ++ "' was not found" where uk = T.unpack k -atPM :: Monad m => Map Text Object -> Text -> (Object -> m a) -> m (Maybe a)-atPM m k conv = traverse conv $ M.lookup k m+atPM :: Monad m => Map Text Object -> Text -> (Text -> Object -> m a) -> m (Maybe a)+atPM m k conv = traverse (conv k) $ M.lookup k m -atPMD :: Monad m => Map Text Object -> Text -> (Object -> m a) -> a -> m a+atPMD :: Monad m => Map Text Object -> Text -> (Text -> Object -> m a) -> a -> m a atPMD m k conv def = do x <- atPM m k conv case x of Just r -> pure r Nothing -> pure def -asStr :: Monad m => Object -> m Text-asStr (ObjectStr s) = pure s-asStr _ = fail "Not a string data"+asStr :: Monad m => Text -> Object -> m Text+asStr _ (ObjectStr s) = pure s+asStr m _ = fail $ T.unpack m <> ": not a string data" -asChar :: Monad m => Object -> m Char-asChar = (head . T.unpack <$>) . asStr+asChar :: Monad m => Text -> Object -> m Char+asChar m = (head . T.unpack <$>) . asStr m -asInt :: (Monad m, Integral a) => Object -> m a-asInt (ObjectInt i) = pure (fromIntegral i)-asInt (ObjectWord w) = pure (fromIntegral w)-asInt _ = fail "Not an int data"+asInt :: (Monad m, Integral a) => Text -> Object -> m a+asInt _ (ObjectInt i) = pure (fromIntegral i)+asInt _ (ObjectWord w) = pure (fromIntegral w)+asInt m _ = fail $ T.unpack m <> ": not an int data" -asFloat :: Monad m => Object -> m Float-asFloat (ObjectFloat f) = pure f-asFloat _ = fail "Not a float data"+asFloat :: Monad m => Text -> Object -> m Float+asFloat _ (ObjectFloat f) = pure f+asFloat _ (ObjectDouble f) = pure (realToFrac f)+asFloat m _ = fail $ T.unpack m <> ": not a float data" -asIntList :: (Monad m, Integral a) => Object -> m [a]-asIntList (ObjectArray l) = traverse asInt l-asIntList _ = fail "Not an array of ints data"+asIntList :: (Monad m, Integral a) => Text -> Object -> m [a]+asIntList m (ObjectArray l) = traverse (asInt m) l+asIntList m _ = fail $ T.unpack m <> ": not an array of ints data" -asStrList :: Monad m => Object -> m [Text]-asStrList (ObjectArray l) = traverse asStr l-asStrList _ = fail "Not an array of string data"+asStrList :: Monad m => Text -> Object -> m [Text]+asStrList m (ObjectArray l) = traverse (asStr m) l+asStrList m _ = fail $ T.unpack m <> ": not an array of string data" -asFloatList :: Monad m => Object -> m [Float]-asFloatList (ObjectArray l) = traverse asFloat l-asFloatList _ = fail "Not an array of float data"+asFloatList :: Monad m => Text -> Object -> m [Float]+asFloatList m (ObjectArray l) = traverse (asFloat m) l+asFloatList m _ = fail $ T.unpack m <> ": not an array of float data" -asObjectList :: Monad m => Object -> m [Object]-asObjectList (ObjectArray l) = pure l-asObjectList _ = fail "Not an array data"+asObjectList :: Monad m => Text -> Object -> m [Object]+asObjectList _ (ObjectArray l) = pure l+asObjectList m _ = fail $ T.unpack m <> ": not an array data" -asBinary :: Monad m => Object -> m ByteString-asBinary (ObjectBin bs) = pure (fromStrict bs)-asBinary _ = fail "Not a binary data"+asBinary :: Monad m => Text -> Object -> m ByteString+asBinary _ (ObjectBin bs) = pure (fromStrict bs)+asBinary m _ = fail $ T.unpack m <> ": not a binary data"
+ src/Bio/MMTF/Structure.hs view
@@ -0,0 +1,104 @@+{-# LANGUAGE DeriveGeneric #-}+module Bio.MMTF.Structure where++import Data.Array ( Array, (!), elems )+import Data.List ( mapAccumL, zip3, zip4 )+import Data.Text ( Text )+import Data.Int ( Int32 )+import Data.Bifunctor ( Bifunctor (..) )+import GHC.Generics ( Generic )+import Control.DeepSeq ( NFData (..) )++import Bio.MMTF.Decode (l2a)+import Bio.MMTF++data Atom = Atom { atomName :: Text+ , atomElement :: Text+ , atomCoords :: (Float, Float, Float)+ , formalCharge :: Int+ , bFactor :: Float+ , occupancy :: Float+ }+ deriving (Show, Eq, Generic)++instance NFData Atom++data Bond = Bond { bondStart :: Int+ , bondEnd :: Int+ , bondOrder :: Int+ }+ deriving (Show, Eq, Generic)++instance NFData Bond++data Residue = Residue { resName :: Text+ , resAtoms :: Array Int Atom+ , resBonds :: Array Int Bond+ , resSecondary :: SecondaryStructure+ }+ deriving (Show, Eq, Generic)++instance NFData Residue++data Chain = Chain { chainName :: Text+ , chainResidues :: Array Int Residue+ }+ deriving (Show, Eq, Generic)++instance NFData Chain++newtype Model = Model { modelChains :: Array Int Chain }+ deriving (Show, Eq, Generic)++instance NFData Model++modelsOf :: MMTF -> Array Int Model+modelsOf m = l2a (Model . l2a <$> zipWith (zipWith Chain) chainNames chainResis)+ where+ chainsCnts = fromIntegral <$> elems (chainsPerModel (model m))+ groupsCnts = fromIntegral <$> elems (groupsPerChain (chain m))+ groupsRaws = snd $ mapAccumL getGroups (0, 0) groupsCnts+ groups = cutter chainsCnts groupsRaws+ chainNames = cutter chainsCnts (elems $ chainNameList $ chain m)+ chainResis = fmap (fmap (l2a . (fmap mkResidue))) groups++ getGroups :: (Int, Int) -> Int -> ((Int, Int), [(GroupType, SecondaryStructure, [Atom])])+ getGroups (chOffset, atOffset) sz = let chEnd = chOffset + sz+ gtl = groupTypeList (group m)+ gl = groupList (group m)+ ssl = secStructList (group m)+ chr = [chOffset .. chEnd - 1]+ rgt = (gl !) . fromIntegral . (gtl !) <$> chr+ rss = (ssl !) <$> chr+ (atEnd, ats) = mapAccumL getAtoms atOffset rgt+ in ((chEnd, atEnd), zip3 rgt rss ats)++ getAtoms :: Int -> GroupType -> (Int, [Atom])+ getAtoms offset gt = let cl = fmap fromIntegral . elems . gtFormalChargeList $ gt+ nl = elems . gtAtomNameList $ gt+ el = elems . gtElementList $ gt+ ics = [offset .. end - 1]+ end = offset + length cl+ in (end, mkAtom <$> zip4 cl nl el ics)++ mkResidue :: (GroupType, SecondaryStructure, [Atom]) -> Residue+ mkResidue (gt, ss, atoms) = Residue (gtGroupName gt) (l2a atoms) (mkBonds (gtBondAtomList gt) (gtBondOrderList gt)) ss++ mkBonds :: Array Int (Int32, Int32) -> Array Int Int32 -> Array Int Bond+ mkBonds bal bol = let ball = bimap fromIntegral fromIntegral <$> elems bal+ boll = fromIntegral <$> elems bol+ res = zipWith (\(f, t) o -> Bond f t o) ball boll+ in l2a res++ mkAtom :: (Int, Text, Text, Int) -> Atom+ mkAtom (fc, n, e, idx) = let x = xCoordList (atom m)+ y = yCoordList (atom m)+ z = zCoordList (atom m)+ o = occupancyList (atom m)+ b = bFactorList (atom m)+ in Atom n e (x ! idx, y ! idx, z ! idx) fc (b ! idx) (o ! idx)++ cutter :: [Int] -> [a] -> [[a]]+ cutter [] [] = []+ cutter (x:xs) ys = take x ys : cutter xs (drop x ys)+ cutter [] (_:_) = error "Cutter: you cannot be here"
src/Bio/MMTF/Type.hs view
@@ -1,8 +1,26 @@+{-# LANGUAGE DeriveGeneric #-} module Bio.MMTF.Type where -import Data.Int (Int32, Int8)-import Data.Text (Text)+import Data.Int ( Int32, Int8 )+import Data.Text ( Text )+import Data.Array ( Array )+import GHC.Generics ( Generic )+import Control.DeepSeq ( NFData (..) ) +-- | All arrays are int-indexed+--+type IArray a = Array Int a++-- | Transformation matrix+--+data M44 = M44 Float Float Float Float+ Float Float Float Float+ Float Float Float Float+ Float Float Float Float+ deriving (Show, Eq, Generic)++instance NFData M44+ -- | Unit cell data -- data UnitCell = UnitCell { ucA :: !Float -- ^ length of side 'a'@@ -12,44 +30,54 @@ , ucBeta :: !Float -- ^ beta angle in degrees , ucGamma :: !Float -- ^ gamma angle in degrees }- deriving (Show, Eq)+ deriving (Show, Eq, Generic) +instance NFData UnitCell+ -- | Transform data ---data Transform = Transform { chainIndexList :: ![Int32] -- ^ indices into the 'chainIdList' and 'chainNameList' fields- , matrix :: ![Float] -- ^ 4x4 transformation matrix+data Transform = Transform { chainIndexList :: !(IArray Int32) -- ^ indices into the 'chainIdList' and 'chainNameList' fields+ , matrix :: !M44 -- ^ 4x4 transformation matrix }- deriving (Show, Eq)+ deriving (Show, Eq, Generic) +instance NFData Transform+ -- | Assembly data ---data Assembly = Assembly { transformList :: ![Transform] -- ^ List of transform objects- , assemblyName :: !Text -- ^ Name of the biological assembly+data Assembly = Assembly { transformList :: !(IArray Transform) -- ^ List of transform objects+ , assemblyName :: !Text -- ^ Name of the biological assembly }- deriving (Show, Eq)+ deriving (Show, Eq, Generic) +instance NFData Assembly+ -- | Entity data ---data Entity = Entity { entityChainIndexList :: ![Int32] -- ^ indices into the 'chainIdList' and 'chainNameList' fields- , entityDescription :: !Text -- ^ Description of the entity- , entityType :: !Text -- ^ Name of the entity type- , entitySequence :: !Text -- ^ Sequence of the full construct in one-letter-code+data Entity = Entity { entityChainIndexList :: !(IArray Int32) -- ^ indices into the 'chainIdList' and 'chainNameList' fields+ , entityDescription :: !Text -- ^ Description of the entity+ , entityType :: !Text -- ^ Name of the entity type+ , entitySequence :: !Text -- ^ Sequence of the full construct in one-letter-code }- deriving (Show, Eq)+ deriving (Show, Eq, Generic) +instance NFData Entity+ -- | Group type data ---data GroupType = GroupType { gtFormalChargeList :: ![Int32] -- ^ List of formal charges- , gtAtomNameList :: ![Text] -- ^ List of atom names- , gtElementList :: ![Text] -- ^ List of elements- , gtBondAtomList :: ![Int32] -- ^ List of bonded atom indices- , gtBondOrderList :: ![Int32] -- ^ List of bond orders- , gtGroupName :: !Text -- ^ The name of the group- , gtSingleLetterCode :: !Char -- ^ The single letter code- , gtChemCompType :: !Text -- ^ The chemical component type+data GroupType = GroupType { gtFormalChargeList :: !(IArray Int32) -- ^ List of formal charges+ , gtAtomNameList :: !(IArray Text) -- ^ List of atom names+ , gtElementList :: !(IArray Text) -- ^ List of elements+ , gtBondAtomList :: !(IArray (Int32, Int32)) -- ^ List of bonded atom indices+ , gtBondOrderList :: !(IArray Int32) -- ^ List of bond orders+ , gtGroupName :: !Text -- ^ The name of the group+ , gtSingleLetterCode :: !Char -- ^ The single letter code+ , gtChemCompType :: !Text -- ^ The chemical component type }- deriving (Show, Eq)+ deriving (Show, Eq, Generic) +instance NFData GroupType+ -- | Protein secondary structure -- data SecondaryStructure = PiHelix -- ^ pi helix@@ -61,77 +89,91 @@ | Turn -- ^ turn | Coil -- ^ coil | Undefined -- ^ unknown structure- deriving (Show, Eq)+ deriving (Show, Eq, Generic) +instance NFData SecondaryStructure+ -- | MMTF format data -- data FormatData = FormatData { mmtfVersion :: !Text -- ^ The version number of the specification the file adheres to , mmtfProducer :: !Text -- ^ The name and version of the software used to produce the file }- deriving (Show, Eq)+ deriving (Show, Eq, Generic) +instance NFData FormatData+ -- | Structure data ---data StructureData = StructureData { title :: !Text -- ^ A short description of the structural data included in the file- , structureId :: !Text -- ^ An ID for the structure, for example the PDB ID if applicable- , depositionDate :: !Text -- ^ A date that relates to the deposition of the structure in a database- , releaseDate :: !Text -- ^ A date that relates to the release of the structure in a database- , numBonds :: !Int32 -- ^ The overall number of bonds- , numAtoms :: !Int32 -- ^ The overall number of atoms in the structure- , numGroups :: !Int32 -- ^ The overall number of groups in the structure- , numChains :: !Int32 -- ^ The overall number of chains in the structure- , numModels :: !Int32 -- ^ The overall number of models in the structure- , spaceGroup :: !Text -- ^ The Hermann-Mauguin space-group symbol- , unitCell :: !(Maybe UnitCell) -- ^ Array of six values defining the unit cell- , ncsOperatorList :: ![[Float]] -- ^ List of lists representing 4x4 transformation matrices that are stored linearly in row major order (transformation matrices describe noncrystallographic symmetry operations needed to create all molecules in the unit cell)- , bioAssemblyList :: ![Assembly] -- ^ List of instructions on how to transform coordinates for an array of chains to create (biological) assemblies- , entityList :: ![Entity] -- ^ List of unique molecular entities within the structure- , resolution :: !(Maybe Float) -- ^ The experimental resolution in Angstrom- , rFree :: !(Maybe Float) -- ^ The R-free value- , rWork :: !(Maybe Float) -- ^ The R-work value- , experimentalMethods :: ![Text] -- ^ List of experimental methods employed for structure determination- , bondAtomList :: ![Int32] -- ^ Pairs of values represent indices of covalently bonded atoms [binary (type 4)]- , bondOrderList :: ![Int8] -- ^ List of bond orders for bonds in 'bondAtomList' [binary (type 2)]+data StructureData = StructureData { title :: !Text -- ^ A short description of the structural data included in the file+ , structureId :: !Text -- ^ An ID for the structure, for example the PDB ID if applicable+ , depositionDate :: !Text -- ^ A date that relates to the deposition of the structure in a database+ , releaseDate :: !Text -- ^ A date that relates to the release of the structure in a database+ , numBonds :: !Int32 -- ^ The overall number of bonds+ , numAtoms :: !Int32 -- ^ The overall number of atoms in the structure+ , numGroups :: !Int32 -- ^ The overall number of groups in the structure+ , numChains :: !Int32 -- ^ The overall number of chains in the structure+ , numModels :: !Int32 -- ^ The overall number of models in the structure+ , spaceGroup :: !Text -- ^ The Hermann-Mauguin space-group symbol+ , unitCell :: !(Maybe UnitCell) -- ^ Array of six values defining the unit cell+ , ncsOperatorList :: !(IArray M44) -- ^ List of 4x4 transformation matrices (transformation matrices describe noncrystallographic symmetry operations needed to create all molecules in the unit cell)+ , bioAssemblyList :: !(IArray Assembly) -- ^ List of instructions on how to transform coordinates for an array of chains to create (biological) assemblies+ , entityList :: !(IArray Entity) -- ^ List of unique molecular entities within the structure+ , resolution :: !(Maybe Float) -- ^ The experimental resolution in Angstrom+ , rFree :: !(Maybe Float) -- ^ The R-free value+ , rWork :: !(Maybe Float) -- ^ The R-work value+ , experimentalMethods :: !(IArray Text) -- ^ List of experimental methods employed for structure determination+ , bondAtomList :: !(IArray (Int32, Int32)) -- ^ Pairs of values represent indices of covalently bonded atoms [binary (type 4)]+ , bondOrderList :: !(IArray Int8) -- ^ List of bond orders for bonds in 'bondAtomList' [binary (type 2)] }- deriving (Show, Eq)+ deriving (Show, Eq, Generic) +instance NFData StructureData+ -- | Models data ---data ModelData = ModelData { chainsPerModel :: ![Int32] -- ^ List of the number of chains in each model+data ModelData = ModelData { chainsPerModel :: !(IArray Int32) -- ^ List of the number of chains in each model }- deriving (Show, Eq)+ deriving (Show, Eq, Generic) +instance NFData ModelData+ -- | Chains data ---data ChainData = ChainData { groupsPerChain :: ![Int32] -- ^ List of the number of groups (aka residues) in each chain- , chainIdList :: ![Text] -- ^ List of chain IDs [binary (type 5)]- , chainNameList :: ![Text] -- ^ List of chain names [binary (type 5)]+data ChainData = ChainData { groupsPerChain :: !(IArray Int32) -- ^ List of the number of groups (aka residues) in each chain+ , chainIdList :: !(IArray Text) -- ^ List of chain IDs [binary (type 5)]+ , chainNameList :: !(IArray Text) -- ^ List of chain names [binary (type 5)] }- deriving (Show, Eq)+ deriving (Show, Eq, Generic) +instance NFData ChainData+ -- | Groups data ---data GroupData = GroupData { groupList :: ![GroupType] -- ^ List of groupType objects- , groupTypeList :: ![Int32] -- ^ List of pointers to 'groupType' entries in 'groupList' by their keys [binary (type 4)]- , groupIdList :: ![Int32] -- ^ List of group (residue) numbers [binary (type 8)]- , secStructList :: ![SecondaryStructure] -- ^ List of secondary structure assignments [binary (type 2)]- , insCodeList :: ![Char] -- ^ List of insertion codes, one for each group (residue) [binary (type 6)]- , sequenceIndexList :: ![Int32] -- ^ List of indices that point into the sequence property of an entity object in the 'entityList' field that is associated with the chain the group belongs to [binary (type 8)]+data GroupData = GroupData { groupList :: !(IArray GroupType) -- ^ List of groupType objects+ , groupTypeList :: !(IArray Int32) -- ^ List of pointers to 'groupType' entries in 'groupList' by their keys [binary (type 4)]+ , groupIdList :: !(IArray Int32) -- ^ List of group (residue) numbers [binary (type 8)]+ , secStructList :: !(IArray SecondaryStructure) -- ^ List of secondary structure assignments [binary (type 2)]+ , insCodeList :: !(IArray Text) -- ^ List of insertion codes, one for each group (residue) [binary (type 6)]+ , sequenceIndexList :: !(IArray Int32) -- ^ List of indices that point into the sequence property of an entity object in the 'entityList' field that is associated with the chain the group belongs to [binary (type 8)] }- deriving (Show, Eq)+ deriving (Show, Eq, Generic) +instance NFData GroupData+ -- | Atoms data ---data AtomData = AtomData { atomIdList :: ![Int32] -- ^ List of atom serial numbers [binary (type 8)]- , altLocList :: ![Char] -- ^ List of alternate location labels, one for each atom [binary (type 6)]- , bFactorList :: ![Float] -- ^ List of atom B-factors in in A^2, one for each atom [binary (type 10)]- , xCoordList :: ![Float] -- ^ List of x atom coordinates in A, one for each atom [binary (type 10)]- , yCoordList :: ![Float] -- ^ List of y atom coordinates in A, one for each atom [binary (type 10)]- , zCoordList :: ![Float] -- ^ List of z atom coordinates in A, one for each atom [binary (type 10)]- , occupancyList :: ![Float] -- ^ List of atom occupancies, one for each atom [binary (type 9)]+data AtomData = AtomData { atomIdList :: !(IArray Int32) -- ^ List of atom serial numbers [binary (type 8)]+ , altLocList :: !(IArray Text) -- ^ List of alternate location labels, one for each atom [binary (type 6)]+ , bFactorList :: !(IArray Float) -- ^ List of atom B-factors in in A^2, one for each atom [binary (type 10)]+ , xCoordList :: !(IArray Float) -- ^ List of x atom coordinates in A, one for each atom [binary (type 10)]+ , yCoordList :: !(IArray Float) -- ^ List of y atom coordinates in A, one for each atom [binary (type 10)]+ , zCoordList :: !(IArray Float) -- ^ List of z atom coordinates in A, one for each atom [binary (type 10)]+ , occupancyList :: !(IArray Float) -- ^ List of atom occupancies, one for each atom [binary (type 9)] }- deriving (Show, Eq)+ deriving (Show, Eq, Generic) +instance NFData AtomData+ -- | MMTF datatype -- data MMTF = MMTF { format :: !FormatData -- ^ MMTF format data@@ -141,4 +183,6 @@ , group :: !GroupData -- ^ Groups data , atom :: !AtomData -- ^ Atoms data }- deriving (Show, Eq)+ deriving (Show, Eq, Generic)++instance NFData MMTF
test/Spec.hs view
@@ -3,6 +3,7 @@ import Bio.MMTF import qualified Data.ByteString.Lazy as B import Data.Int (Int8)+import Data.Array ((!)) import Test.Hspec import Bio.MMTF.Decode.Codec@@ -19,7 +20,7 @@ it "unpacks by Recursive indexing encoding" $ do let sample = [ 127, 41, 34, 1, 0, -50, -128, 0, 7, 127, 0, 127, 127, 14 ] :: [Int8] recIndexDec sample `shouldBe` [ 168, 34, 1, 0, -50, -128, 7, 127, 268 ]- it "upacks by Integer encoding" $ do+ it "unpacks by Integer encoding" $ do let sample = [ 100, 100, 100, 100, 50, 50 ] :: [Int8] integerDec 100 sample `shouldBe` [ 1.00, 1.00, 1.00, 1.00, 0.50, 0.50 ] @@ -31,9 +32,9 @@ (structureId . structure) m `shouldBe` "1FSD" (numModels . structure) m `shouldBe` 41 (length . bFactorList . atom) m `shouldBe` 20664- (experimentalMethods . structure) m `shouldBe` ["SOLUTION NMR"]- (head . xCoordList . atom) m `shouldBe` (-12.847)- (last . xCoordList . atom) m `shouldBe` 5.672+ ((! 0) . experimentalMethods . structure) m `shouldBe` "SOLUTION NMR"+ ((! 0) . xCoordList . atom) m `shouldBe` (-12.847)+ ((! 20663) . xCoordList . atom) m `shouldBe` 5.672 main :: IO () main = hspec $ do