{- EnsemblConvert Gregory W. Schwartz Collections the functions pertaining to converting certain annotations into ensembl annotations. -} {-# LANGUAGE ViewPatterns #-} {-# LANGUAGE OverloadedStrings #-} module EnsemblConvert ( toEnsemblAnn , toEnsemblDesc ) where -- Standard import Data.Maybe import Data.List import qualified Data.Map.Strict as Map import Data.Monoid -- Cabal import qualified Data.ByteString.Lazy.Char8 as CL import qualified Data.Text as T import Data.Aeson import Data.Aeson.Types import Network.HTTP import Safe -- Local import Types -- | Null the null value of an object. If the object is Null, return "". nullNull :: Value -> Parser T.Text nullNull (String x) = return $ x nullNull _ = return $ "" -- | Decode a Ensembl id query as an Ensembl identifier. decodeEnsemblAnn :: CL.ByteString -> Maybe Ann decodeEnsemblAnn "" = Nothing decodeEnsemblAnn query = getENSG ( eitherDecode query :: Either String ([Map.Map T.Text T.Text]) ) where getENSG = fmap Ann . headMay . filter (T.isPrefixOf "ENSG") . concatMap Map.elems . either error id -- | Decode a Ensembl id query as a description of the id. decodeEnsemblDesc :: DescFields -> CL.ByteString -> Desc decodeEnsemblDesc _ "" = Desc "" decodeEnsemblDesc field query = Desc . T.intercalate "/" . filter (not . T.null) . fmap (parse field) . either (error . ("In initial decoding: " <>)) id $ (eitherDecode query :: Either String [Object]) where parse :: DescFields -> Object -> T.Text parse Synonyms = T.intercalate "/" . filter (not . T.null) . either (error . ("In synonym decoding: " <>)) id . parseEither (flip (.:) "synonyms") parse Description = either (error . ("In description decoding: " <>)) id . parseEither ((=<<) nullNull . flip (.:) "description") getDesc = Desc . T.intercalate "/" . filter (not . T.null) . fmap (parse field) -- | Get Ensembl annotation. toEnsemblAnn :: UnknownAnn -> IO (Maybe Ann) toEnsemblAnn (UnknownAnn "") = return Nothing toEnsemblAnn (UnknownAnn query) = do let base = "http://rest.ensembl.org/" xrefs = "xrefs/symbol/homo_sapiens/" xrefOpts = "?content-type=application/json;all_levels=1" xrefReq = base <> xrefs <> T.unpack query <> xrefOpts xrefRsp <- simpleHTTP (getRequest xrefReq) >>= getResponseBody let ensemblAnn = case xrefRsp of "[]" -> Nothing (stripPrefix "{\"error\":" -> Just _) -> Nothing x -> decodeEnsemblAnn . CL.pack $ x return ensemblAnn -- | Get Ensembl description. toEnsemblDesc :: DescFields -> UnknownAnn -> IO (Maybe Desc) toEnsemblDesc _ (UnknownAnn "") = return Nothing toEnsemblDesc field (UnknownAnn query) = do let base = "http://rest.ensembl.org/" xrefs = "xrefs/id/" xrefOpts = "?content-type=application/json;all_levels=1" xrefReq = base <> xrefs <> T.unpack query <> xrefOpts xrefRsp <- simpleHTTP (getRequest xrefReq) >>= getResponseBody let ensemblDesc = case xrefRsp of "[]" -> Nothing (stripPrefix "{\"error\":" -> Just _) -> Nothing x -> Just . decodeEnsemblDesc field . CL.pack $ x return ensemblDesc