packages feed

convert-annotation 0.2.0.1 → 0.4.0.0

raw patch · 6 files changed

+247/−26 lines, 6 filesdep +inline-r

Dependencies added: inline-r

Files

+ README.org view
@@ -0,0 +1,33 @@+* convert-annotation++Very early stages. Mix between =HTTP= and =wreq= libraries, need to fully+convert to =wreq= in the future.++Each mode, =info= or =annotation=, has its own help.++Main usage to convert, say, some unknown annotation to Ensembl annotation in a+=csv=:++#+BEGIN_SRC sh+cat input.csv | convert-annotation annotation --database "Ensembl" --column "gene"+#+END_SRC++#+BEGIN_SRC sh :exports results :results value code+convert-annotation -h+#+END_SRC++#+RESULTS:+#+BEGIN_SRC sh+convert-annotation, Gregory W. Schwartz. Converts an unknown annotation to some+other annotation.++Usage: convert-annotation (info | annotation)++Available options:+  -h,--help                Show this help text++Available commands:+  info                     +  annotation               +#+END_SRC+
app/Main.hs view
@@ -4,6 +4,7 @@ Converts an unknown annotation to Ensembl's annotation, or other annotation. -} +{-# LANGUAGE BangPatterns      #-} {-# LANGUAGE DataKinds         #-} {-# LANGUAGE DeriveGeneric     #-} {-# LANGUAGE OverloadedStrings #-}@@ -17,6 +18,7 @@ import Data.List import Control.Monad import GHC.Generics+import Data.Semigroup  -- Cabal import qualified Data.Text as T@@ -28,30 +30,42 @@ import Pipes.Csv import Options.Generic +import qualified Foreign.R as R+import Foreign.R (SEXP, SEXPTYPE)+import Language.R.Instance as R+import Language.R.QQ+import Language.R.Literal as R+ -- Local import Types import EnsemblConvert import HUGOConvert import UniProtConvert+import RGeneConvert+import MSigDBRDataConvert  -- | Command line arguments data Options = Info { delimiter        :: Maybe String                                       <?> "([,] | CHAR) The delimiter of the CSV file."                     , database         :: String-                                      <?> "(Ensembl | HUGO TYPE | UniProt) Which database to convert with. TYPE is the type of the original gene symbol. The compatible list is in http://www.genenames.org/help/rest-web-service-help. HUGO is only supported for Annotation."-                    , descriptionField :: String+                                      <?> "(Ensembl | HUGO TYPE | UniProt | RGene (TYPE, TYPE) | MSigDBRdata (FILE, RDATA, TYPE)) Which database to convert with. TYPE is the type of the original gene symbol. The compatible list for TYPE with HUGO is in http://www.genenames.org/help/rest-web-service-help. HUGO is only supported for Annotation. RGene (Annotation only) takes in a type of (FROM, TO) for the gene symbol origin and destination. MSigDBRdata (Info only) takes an rdata file (tested with http://bioinf.wehi.edu.au/software/MSigDB/), the name of the rdata object containing the named list, and the TYPE of symbol (compatable list at http://bioconductor.org/packages/release/bioc/manuals/biomaRt/man/biomaRt.pdf in getGene) which returns pathways separated by \"/\"."+                    , descriptionField :: Maybe String                                       <?> "(Other TEXT | Description | Synonyms) The info to retrieve about the identifier. Description provides information about the identifier while synonyms provides alternate identifiers for the same entity. Returns a list of information (delimited by '/') for each match to Ensembl's cross references. For UniProt, enter a valid column (http://www.uniprot.org/help/programmatic_access)."                     , column           :: T.Text                                       <?> "(COLUMN) The column containing the identifier. Must be a valid id for info."+                    , newColumn        :: Maybe T.Text+                                      <?> "([Nothing] | COLUMN) The new column to put the results into. If unspecified, replaces the original column."                     , remove           :: Bool                                       <?> "Whether to remove empty results (no matches to the database)."                     }              | Annotation { delimiter :: Maybe String                                      <?> "([,] | CHAR) The delimiter of the CSV file."                           , database  :: String-                                     <?> "(Ensembl | HUGO TYPE | UniProt) Which database to convert with. TYPE is the type of the original gene symbol. The compatible list is in http://www.genenames.org/help/rest-web-service-help. HUGO is only supported for Annotation."+                                     <?> "(Ensembl | HUGO TYPE | UniProt | RGene (TYPE, TYPE) | MSigDBRdata (FILE, RDATA, TYPE)) Which database to convert with. TYPE is the type of the original gene symbol. The compatible list for TYPE with HUGO is in http://www.genenames.org/help/rest-web-service-help. HUGO is only supported for Annotation. RGene (Annotation only) takes in a type of (FROM, TO) for the gene symbol origin and destination. MSigDBRdata (Info only) takes an rdata file (tested with http://bioinf.wehi.edu.au/software/MSigDB/), the name of the rdata object containing the named list, and the TYPE of symbol (compatable list at http://bioconductor.org/packages/release/bioc/manuals/biomaRt/man/biomaRt.pdf in getGene) which returns pathways separated by \"/\"."                           , column    :: T.Text                                      <?> "(COLUMN) The column containing the identifier. Must be a valid id for info."+                          , newColumn :: Maybe T.Text+                                     <?> "([Nothing] | COLUMN) The new column to put the results into. If unspecified, replaces the original column."                           , remove    :: Bool                                      <?> "Whether to remove empty results (no matches to the database)."                           }@@ -61,20 +75,25 @@  -- | Map the header column to the rest of the file for converting that -- column.-pipeConvert :: Options -> Pipe [T.Text] [T.Text] IO ()-pipeConvert opts = do+pipeConvert :: Options+            -> Maybe (RMart s)+            -> Maybe (RData s)+            -> Pipe [T.Text] [T.Text] IO ()+pipeConvert opts rMart rData = do     h <- await -    let c = col opts h+    let c      = col opts h+        newCol = unHelpful . newColumn $ opts -    yield h+    yield . maybe h (\x -> h <> [x]) $ newCol      forever $ do         x    <- await-        newX <- lift . convert opts . (!! c) $ x-        unless-            ((unHelpful . remove $ opts) && T.null newX)-            (yield . L.set (L.ix c) newX $ x)+        newX <- lift . convert opts rMart rData . (!! c) $ x+        unless ((unHelpful . remove $ opts) && T.null newX)+            . maybe (yield . L.set (L.ix c) newX $ x)+                    (const (yield (x <> [newX])))+            $ newCol         return ()      return ()@@ -85,23 +104,41 @@     fromMaybe (error "Column not found.") . elemIndex (unHelpful $ column opts)  -- | The conversion process.-convert :: Options -> T.Text -> IO T.Text-convert opts@(Info { descriptionField = df }) =+convert :: Options -> Maybe (RMart s) -> Maybe (RData s) -> T.Text -> IO T.Text+convert opts@(Info { descriptionField = df }) rMart rData =     fmap (fromMaybe "" . fmap unDesc)         . whichDesc (read . unHelpful . database $ opts)         . UnknownAnn   where-    whichDesc Ensembl  = toEnsemblDesc (read . unHelpful $ df)+    whichDesc Ensembl  = toEnsemblDesc ( read+                                       . fromMaybe (error "Needs description field.")+                                       . unHelpful+                                       $ df+                                       )     whichDesc (HUGO _) = error "HUGO description not yet supported."-    whichDesc UniProt  = toUniProtDesc (read . unHelpful $ df)-convert opts@(Annotation {})                  =+    whichDesc UniProt  = toUniProtDesc ( read+                                       . fromMaybe (error "Needs description field.")+                                       . unHelpful+                                       $ df+                                       )+    whichDesc (RGene _) = error "RGene description not yet supported."+    whichDesc (MSigDBRData queryType) =+        toMSigDBPathways+            (fromJust rData)+            (fromJust rMart)+            (MSigDBType queryType)+convert opts@(Annotation {}) rMart rData                  =     fmap (fromMaybe "" . fmap unAnn)         . whichAnn (read . unHelpful . database $ opts)         . UnknownAnn   where-    whichAnn Ensembl          = toEnsemblAnn-    whichAnn (HUGO queryType) = toHUGOAnn . HUGOType $ queryType-    whichAnn UniProt          = toUniProtAnn+    whichAnn Ensembl           = toEnsemblAnn+    whichAnn (HUGO queryType)  = toHUGOAnn . HUGOType $ queryType+    whichAnn UniProt           = toUniProtAnn+    whichAnn (RGene queryType) =+        toRGeneAnn (fromJust rMart) (RType queryType)+    whichAnn (MSigDBRData _)   =+        error "MSigDBRData annotation not yet supported."  main :: IO () main = do@@ -118,10 +155,20 @@         csvOpts = CSV.defaultDecodeOptions                     { CSV.decDelimiter = fromIntegral (ord delim) } -    runEffect $ decodeWith csvOpts NoHeader PB.stdin+    R.withEmbeddedR R.defaultConfig $ R.runRegion $ do+        rMart <- case read . unHelpful . database $ opts of+                    (RGene _)       -> fmap Just getRMart+                    (MSigDBRData _) -> fmap Just getRMart+                    _               -> return Nothing+        rData <- case read . unHelpful . database $ opts of+                    (MSigDBRData (!file, !object, _)) ->+                        fmap Just . getRData (File file) $ object+                    _                                 -> return Nothing++        liftIO $ runEffect $ decodeWith csvOpts NoHeader PB.stdin             >-> P.concat-            >-> (pipeConvert opts)+            >-> (pipeConvert opts rMart rData)             >-> encode             >-> PB.stdout -    return ()+        return ()
convert-annotation.cabal view
@@ -1,7 +1,7 @@ name:                convert-annotation-version:             0.2.0.1+version:             0.4.0.0 synopsis:            Convert the annotation of a gene to another in a delimited file using a variety of different databases.-description:         Please see README.md+description:         Please see README.org homepage:            http://github.com/GregorySchwartz/convert-annotation#readme license:             GPL-3 license-file:        LICENSE@@ -10,7 +10,7 @@ copyright:           Copyright: (c) 2016 Gregory W. Schwartz category:            Bioinformatics build-type:          Simple--- extra-source-files:+extra-source-files:  README.org cabal-version:       >=1.10  library@@ -19,6 +19,8 @@                      , EnsemblConvert                      , HUGOConvert                      , UniProtConvert+                     , RGeneConvert+                     , MSigDBRDataConvert   build-depends:       base >= 4.7 && < 5                      , containers                      , bytestring@@ -29,6 +31,7 @@                      , wreq                      , HTTP                      , safe+                     , inline-r    ghc-options:         -O2   default-language:    Haskell2010@@ -47,6 +50,7 @@                      , pipes-bytestring                      , pipes-csv                      , lens+                     , inline-r   default-language:    Haskell2010  source-repository head
+ src/MSigDBRDataConvert.hs view
@@ -0,0 +1,64 @@+{- MSigDBRDataConvert+Gregory W. Schwartz++Collections the functions pertaining to converting certain annotations into+pathways using the MSigDB rdata files (tested with+http://bioinf.wehi.edu.au/software/MSigDB/).+-}++{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE QuasiQuotes #-}++module MSigDBRDataConvert+    ( getRData+    , toMSigDBPathways+    ) where++-- Standard++-- Cabal+import qualified Data.Text as T++import qualified Foreign.R as R+import Foreign.R (SEXP, SEXPTYPE)+import Language.R.Instance as R+import Language.R.QQ+import Language.R.Literal as R+import H.Prelude++-- Local+import Types+import RGeneConvert+       +-- | Get the RData object.+getRData :: File -> String -> R s (RData s)+getRData (File file) object = fmap RData+                            $ [r| load(file_hs)+                                  res = get(object_hs)+                                  res+                              |]++-- | Get the R mapping of gene to gene.+toMSigDBPathways+    :: RData s+    -> RMart s+    -> MSigDBType+    -> UnknownAnn+    -> IO (Maybe Desc)+toMSigDBPathways _ _ _ (UnknownAnn "")            = return Nothing+toMSigDBPathways rData rMart (MSigDBType (_, _, !from)) query =+    (fmap . fmap) Desc $ R.runRegion $ do+      entrez <- io . toRGeneAnn rMart (RType (from, "entrezgene")) $ query+      let object = unRData rData++      case entrez of+          Nothing            -> return Nothing+          (Just (Ann gText)) -> do+              let g = T.unpack gText+              res <- [r| pathNames = names(object_hs[unlist(lapply(object_hs, function(x) (g_hs %in% unlist(x))))]) |]+              let pathNames = R.fromSomeSEXP res :: [String]+              if null . drop 1 $ pathNames+                  then return Nothing+                  else+                    return . Just . T.intercalate "/" . fmap T.pack $ pathNames
+ src/RGeneConvert.hs view
@@ -0,0 +1,57 @@+{- RGeneConvert+Gregory W. Schwartz++Collections the functions pertaining to converting certain annotations into+other annotations using biomart from R+(http://bioconductor.org/packages/release/bioc/html/biomaRt.html).+-}++{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE QuasiQuotes #-}++module RGeneConvert+    ( getRMart+    , toRGeneAnn+    ) where++-- Standard++-- Cabal+import qualified Data.Text as T++import qualified Foreign.R as R+import Foreign.R (SEXP, SEXPTYPE)+import Language.R.Instance as R+import Language.R.QQ+import Language.R.Literal as R++-- Local+import Types++-- | Get the R mapping of gene to gene.+getRMart :: R s (RMart s)+getRMart = fmap RMart+         $ [r| library(biomaRt)+               mart = useMart("ensembl", dataset="hsapiens_gene_ensembl")+           |]++-- | Get the R mapping of gene to gene.+toRGeneAnn :: RMart s -> RType -> UnknownAnn -> IO (Maybe Ann)+toRGeneAnn _ _ (UnknownAnn "")            = return Nothing+toRGeneAnn rMart (RType (!from, !to)) (UnknownAnn textQuery) =+    (fmap . fmap) Ann $ R.runRegion $ do+      let query = T.unpack textQuery+          mart  = unRMart rMart+      res <- [r| map = getBM( attributes = c(from_hs, to_hs)+                            , filters = from_hs+                            , values = c(query_hs)+                            , mart = mart_hs+                            , uniqueRows=FALSE+                            )+                as.character(map[1,2])+            |]++      let naCheck "NA" = Nothing+          naCheck x    = Just x+      return . fmap T.pack . naCheck $ (R.fromSomeSEXP res :: String)
src/Types.hs view
@@ -15,20 +15,36 @@ import qualified Data.Text as T import Data.Aeson +import qualified Foreign.R as R+import Foreign.R (SEXP, SEXPTYPE)+import Language.R.Instance as R+import Language.R.QQ+ -- Local   -- Algebraic-data Database = Ensembl | HUGO T.Text | UniProt deriving (Read, Show)+data Database+    = Ensembl+    | HUGO T.Text+    | UniProt+    | RGene (String, String)+    | MSigDBRData (String, String, String)+    deriving (Read,Show) data DescFields = UniProtOther T.Text                 | Synonyms                 | Description                   deriving (Read,Show)  -- Basic+newtype File        = File String newtype UnknownAnn  = UnknownAnn { unUnknownAnn :: T.Text } newtype Ann         = Ann { unAnn :: T.Text } newtype Desc        = Desc { unDesc :: T.Text } newtype HUGOType    = HUGOType { unHUGOType :: T.Text }+newtype RType       = RType { unRType :: (String, String) }+newtype MSigDBType  = MSigDBType { unMSigDBType :: (String, String, String) }+newtype RMart s     = RMart { unRMart :: (R.SomeSEXP s) }+newtype RData s     = RData { unRData :: (R.SomeSEXP s) }  -- Advanced