{-# LANGUAGE OverloadedStrings #-}
module Poseidon.CLI.Genoconvert where
import Poseidon.EntityTypes (HasNameAndVersion (..))
import Poseidon.GenotypeData (GenoDataSource (..),
GenotypeDataSpec (..),
GenotypeFileSpec (..),
loadGenotypeData,
printSNPCopyProgress)
import Poseidon.Janno (jannoRows2EigenstratIndEntries)
import Poseidon.Package (PackageReadOptions (..),
PoseidonPackage (..),
defaultPackageReadOptions,
makePseudoPackageFromGenotypeData,
readPoseidonPackageCollection,
writePoseidonPackage)
import Poseidon.Utils (PoseidonException (..), PoseidonIO,
envErrorLength, envLogAction,
logError, logInfo, logWarning)
import Control.Exception (catch, throwIO)
import Control.Monad (unless, when)
import Data.List ((\\))
import Data.Maybe (isJust)
import Data.Time (getCurrentTime)
import Pipes (MonadIO (liftIO), runEffect, (>->))
import Pipes.Safe (runSafeT)
import SequenceFormats.Eigenstrat (writeEigenstrat)
import SequenceFormats.Plink (PlinkPopNameMode,
eigenstratInd2PlinkFam, writePlink)
import System.Directory (createDirectoryIfMissing,
doesFileExist, removeFile,
renameFile)
import System.Exit (ExitCode (..), exitWith)
import System.FilePath (dropTrailingPathSeparator, (<.>),
(</>))
data GenoconvertOptions = GenoconvertOptions
{ GenoconvertOptions -> [GenoDataSource]
_genoconvertGenoSources :: [GenoDataSource]
, GenoconvertOptions -> [Char]
_genoConvertOutFormat :: String
, GenoconvertOptions -> Maybe [Char]
_genoMaybeOutPackagePath :: Maybe FilePath
, GenoconvertOptions -> Bool
_genoconvertRemoveOld :: Bool
, GenoconvertOptions -> PlinkPopNameMode
_genoconvertOutPlinkPopMode :: PlinkPopNameMode
, GenoconvertOptions -> Bool
_genoconvertOnlyLatest :: Bool
, GenoconvertOptions -> Bool
_genoconvertOutZip :: Bool
}
runGenoconvert :: GenoconvertOptions -> PoseidonIO ()
runGenoconvert :: GenoconvertOptions -> PoseidonIO ()
runGenoconvert (GenoconvertOptions [GenoDataSource]
genoSources [Char]
outFormat Maybe [Char]
outPath
Bool
removeOld PlinkPopNameMode
outPlinkPopMode Bool
onlyLatest Bool
outZip) = do
let pacReadOpts :: PackageReadOptions
pacReadOpts = PackageReadOptions
defaultPackageReadOptions {
_readOptIgnoreChecksums :: Bool
_readOptIgnoreChecksums = Bool
True
, _readOptIgnoreGeno :: Bool
_readOptIgnoreGeno = Bool
False
, _readOptGenoCheck :: Bool
_readOptGenoCheck = Bool
True
, _readOptOnlyLatest :: Bool
_readOptOnlyLatest = Bool
onlyLatest
}
[PoseidonPackage]
properPackages <- PackageReadOptions -> [[Char]] -> PoseidonIO [PoseidonPackage]
readPoseidonPackageCollection PackageReadOptions
pacReadOpts ([[Char]] -> PoseidonIO [PoseidonPackage])
-> [[Char]] -> PoseidonIO [PoseidonPackage]
forall a b. (a -> b) -> a -> b
$
[GenoDataSource -> [Char]
getPacBaseDir GenoDataSource
x | x :: GenoDataSource
x@PacBaseDir {} <- [GenoDataSource]
genoSources]
[PoseidonPackage]
pseudoPackages <- (GenotypeDataSpec -> ReaderT Env IO PoseidonPackage)
-> [GenotypeDataSpec] -> PoseidonIO [PoseidonPackage]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM GenotypeDataSpec -> ReaderT Env IO PoseidonPackage
makePseudoPackageFromGenotypeData
[GenoDataSource -> GenotypeDataSpec
getGenoDirect GenoDataSource
x | x :: GenoDataSource
x@GenoDirect {} <- [GenoDataSource]
genoSources]
[Char] -> PoseidonIO ()
logInfo ([Char] -> PoseidonIO ()) -> [Char] -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ [Char]
"Unpackaged genotype data files loaded: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show ([PoseidonPackage] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [PoseidonPackage]
pseudoPackages)
(PoseidonPackage -> PoseidonIO ())
-> [PoseidonPackage] -> PoseidonIO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ ([Char]
-> Bool
-> Maybe [Char]
-> Bool
-> PlinkPopNameMode
-> Bool
-> PoseidonPackage
-> PoseidonIO ()
convertGenoTo [Char]
outFormat Bool
False Maybe [Char]
outPath Bool
removeOld PlinkPopNameMode
outPlinkPopMode Bool
outZip) [PoseidonPackage]
properPackages
(PoseidonPackage -> PoseidonIO ())
-> [PoseidonPackage] -> PoseidonIO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ ([Char]
-> Bool
-> Maybe [Char]
-> Bool
-> PlinkPopNameMode
-> Bool
-> PoseidonPackage
-> PoseidonIO ()
convertGenoTo [Char]
outFormat Bool
True Maybe [Char]
outPath Bool
removeOld PlinkPopNameMode
outPlinkPopMode Bool
outZip) [PoseidonPackage]
pseudoPackages
convertGenoTo :: String -> Bool -> Maybe FilePath -> Bool ->
PlinkPopNameMode -> Bool -> PoseidonPackage -> PoseidonIO ()
convertGenoTo :: [Char]
-> Bool
-> Maybe [Char]
-> Bool
-> PlinkPopNameMode
-> Bool
-> PoseidonPackage
-> PoseidonIO ()
convertGenoTo [Char]
outFormat Bool
onlyGeno Maybe [Char]
outPath Bool
removeOld PlinkPopNameMode
outPlinkPopMode Bool
outZip PoseidonPackage
pac = do
[Char] -> PoseidonIO ()
logInfo ([Char] -> PoseidonIO ()) -> [Char] -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$
[Char]
"Converting genotype data in "
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ PacNameAndVersion -> [Char]
forall a. Show a => a -> [Char]
show (PoseidonPackage -> PacNameAndVersion
posPacNameAndVersion PoseidonPackage
pac)
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" to format "
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char] -> [Char]
forall a. Show a => a -> [Char]
show [Char]
outFormat
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ if Bool
outZip then [Char]
" (gzipped):" else [Char]
":"
let outName :: [Char]
outName = PacNameAndVersion -> [Char]
forall a. HasNameAndVersion a => a -> [Char]
getPacName (PacNameAndVersion -> [Char])
-> (PoseidonPackage -> PacNameAndVersion)
-> PoseidonPackage
-> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PoseidonPackage -> PacNameAndVersion
posPacNameAndVersion (PoseidonPackage -> [Char]) -> PoseidonPackage -> [Char]
forall a b. (a -> b) -> a -> b
$ PoseidonPackage
pac
let gz :: [Char]
gz = if Bool
outZip then [Char]
"gz" else [Char]
""
([Char]
outIrel, [Char]
outSrel, [Char]
outGrel) <- case [Char]
outFormat of
[Char]
"EIGENSTRAT" -> ([Char], [Char], [Char]) -> ReaderT Env IO ([Char], [Char], [Char])
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return
([Char]
outName [Char] -> [Char] -> [Char]
<.> [Char]
".ind", [Char]
outName [Char] -> [Char] -> [Char]
<.> [Char]
".snp" [Char] -> [Char] -> [Char]
<.> [Char]
gz, [Char]
outName [Char] -> [Char] -> [Char]
<.> [Char]
".geno" [Char] -> [Char] -> [Char]
<.> [Char]
gz)
[Char]
"PLINK" -> ([Char], [Char], [Char]) -> ReaderT Env IO ([Char], [Char], [Char])
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return
([Char]
outName [Char] -> [Char] -> [Char]
<.> [Char]
".fam", [Char]
outName [Char] -> [Char] -> [Char]
<.> [Char]
".bim" [Char] -> [Char] -> [Char]
<.> [Char]
gz, [Char]
outName [Char] -> [Char] -> [Char]
<.> [Char]
".bed" [Char] -> [Char] -> [Char]
<.> [Char]
gz)
[Char]
_ -> IO ([Char], [Char], [Char])
-> ReaderT Env IO ([Char], [Char], [Char])
forall a. IO a -> ReaderT Env IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO ([Char], [Char], [Char])
-> ReaderT Env IO ([Char], [Char], [Char]))
-> ([Char] -> IO ([Char], [Char], [Char]))
-> [Char]
-> ReaderT Env IO ([Char], [Char], [Char])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PoseidonException -> IO ([Char], [Char], [Char])
forall e a. Exception e => e -> IO a
throwIO (PoseidonException -> IO ([Char], [Char], [Char]))
-> ([Char] -> PoseidonException)
-> [Char]
-> IO ([Char], [Char], [Char])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> PoseidonException
PoseidonGenericException ([Char] -> ReaderT Env IO ([Char], [Char], [Char]))
-> [Char] -> ReaderT Env IO ([Char], [Char], [Char])
forall a b. (a -> b) -> a -> b
$
[Char]
"Illegal outFormat " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
outFormat [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++
[Char]
". Only Outformats EIGENSTRAT or PLINK are allowed at the moment"
[Char]
newBaseDir <- case Maybe [Char]
outPath of
Just [Char]
x -> do
[Char] -> PoseidonIO ()
logInfo ([Char] -> PoseidonIO ()) -> [Char] -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ [Char]
"Writing to directory (will be created if missing): " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
x
IO () -> PoseidonIO ()
forall a. IO a -> ReaderT Env IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> PoseidonIO ()) -> IO () -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ Bool -> [Char] -> IO ()
createDirectoryIfMissing Bool
True ([Char] -> [Char]
dropTrailingPathSeparator [Char]
x)
[Char] -> ReaderT Env IO [Char]
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return [Char]
x
Maybe [Char]
Nothing -> [Char] -> ReaderT Env IO [Char]
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ([Char] -> ReaderT Env IO [Char])
-> [Char] -> ReaderT Env IO [Char]
forall a b. (a -> b) -> a -> b
$ PoseidonPackage -> [Char]
posPacBaseDir PoseidonPackage
pac
let ([Char]
outGabs, [Char]
outSabs, [Char]
outIabs) = ([Char]
newBaseDir [Char] -> [Char] -> [Char]
</> [Char]
outGrel, [Char]
newBaseDir [Char] -> [Char] -> [Char]
</> [Char]
outSrel, [Char]
newBaseDir [Char] -> [Char] -> [Char]
</> [Char]
outIrel)
Bool
allExists <- [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
and ([Bool] -> Bool) -> ReaderT Env IO [Bool] -> ReaderT Env IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ([Char] -> ReaderT Env IO Bool)
-> [[Char]] -> ReaderT Env IO [Bool]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM [Char] -> ReaderT Env IO Bool
checkFile [[Char]
outGabs, [Char]
outSabs, [Char]
outIabs]
if Bool
allExists
then do
if Bool
onlyGeno
then do
[Char] -> PoseidonIO ()
logError ([Char] -> PoseidonIO ()) -> [Char] -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ [Char]
"No files were created or overwritten for " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ PacNameAndVersion -> [Char]
forall a. Show a => a -> [Char]
show (PoseidonPackage -> PacNameAndVersion
posPacNameAndVersion PoseidonPackage
pac)
IO () -> PoseidonIO ()
forall a. IO a -> ReaderT Env IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> PoseidonIO ()) -> IO () -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ ExitCode -> IO ()
forall a. ExitCode -> IO a
exitWith (Int -> ExitCode
ExitFailure Int
1)
else
[Char] -> PoseidonIO ()
logWarning ([Char] -> PoseidonIO ()) -> [Char] -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ [Char]
"Package already in desired file-type, skipping genotype conversion for " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++
PacNameAndVersion -> [Char]
forall a. Show a => a -> [Char]
show (PoseidonPackage -> PacNameAndVersion
posPacNameAndVersion PoseidonPackage
pac)
else do
[Char] -> PoseidonIO ()
logInfo [Char]
"Processing SNPs..."
LogA
logA <- PoseidonIO LogA
envLogAction
UTCTime
currentTime <- IO UTCTime -> ReaderT Env IO UTCTime
forall a. IO a -> ReaderT Env IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO UTCTime
getCurrentTime
ErrorLength
errLength <- PoseidonIO ErrorLength
envErrorLength
let eigenstratIndEntries :: [EigenstratIndEntry]
eigenstratIndEntries = JannoRows -> [EigenstratIndEntry]
jannoRows2EigenstratIndEntries (JannoRows -> [EigenstratIndEntry])
-> (PoseidonPackage -> JannoRows)
-> PoseidonPackage
-> [EigenstratIndEntry]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PoseidonPackage -> JannoRows
posPacJanno (PoseidonPackage -> [EigenstratIndEntry])
-> PoseidonPackage -> [EigenstratIndEntry]
forall a b. (a -> b) -> a -> b
$ PoseidonPackage
pac
let zipEnding :: [Char]
zipEnding = if Bool
outZip then [Char]
".gz" else [Char]
""
IO () -> PoseidonIO ()
forall a. IO a -> ReaderT Env IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> PoseidonIO ()) -> IO () -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ IO () -> (SomeException -> IO ()) -> IO ()
forall e a. Exception e => IO a -> (e -> IO a) -> IO a
catch (
SafeT IO () -> IO ()
forall (m :: * -> *) r.
(MonadMask m, MonadIO m) =>
SafeT m r -> m r
runSafeT (SafeT IO () -> IO ()) -> SafeT IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
Producer (EigenstratSnpEntry, GenoLine) (SafeT IO) ()
eigenstratProd <- [Char]
-> GenotypeDataSpec
-> SafeT IO (Producer (EigenstratSnpEntry, GenoLine) (SafeT IO) ())
forall (m :: * -> *).
MonadSafe m =>
[Char]
-> GenotypeDataSpec
-> m (Producer (EigenstratSnpEntry, GenoLine) m ())
loadGenotypeData (PoseidonPackage -> [Char]
posPacBaseDir PoseidonPackage
pac) (PoseidonPackage -> GenotypeDataSpec
posPacGenotypeData PoseidonPackage
pac)
let outConsumer :: Consumer (EigenstratSnpEntry, GenoLine) (SafeT IO) ()
outConsumer = case [Char]
outFormat of
[Char]
"EIGENSTRAT" -> [Char]
-> [Char]
-> [Char]
-> [EigenstratIndEntry]
-> Consumer (EigenstratSnpEntry, GenoLine) (SafeT IO) ()
forall (m :: * -> *).
MonadSafe m =>
[Char]
-> [Char]
-> [Char]
-> [EigenstratIndEntry]
-> Consumer (EigenstratSnpEntry, GenoLine) m ()
writeEigenstrat ([Char]
outGabs [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
".gconvert" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
zipEnding)
([Char]
outSabs [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
".gconvert" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
zipEnding)
([Char]
outIabs [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
".gconvert")
[EigenstratIndEntry]
eigenstratIndEntries
[Char]
"PLINK" -> [Char]
-> [Char]
-> [Char]
-> [PlinkFamEntry]
-> Consumer (EigenstratSnpEntry, GenoLine) (SafeT IO) ()
forall (m :: * -> *).
MonadSafe m =>
[Char]
-> [Char]
-> [Char]
-> [PlinkFamEntry]
-> Consumer (EigenstratSnpEntry, GenoLine) m ()
writePlink ([Char]
outGabs [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
".gconvert" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
zipEnding)
([Char]
outSabs [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
".gconvert" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
zipEnding)
([Char]
outIabs [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
".gconvert")
((EigenstratIndEntry -> PlinkFamEntry)
-> [EigenstratIndEntry] -> [PlinkFamEntry]
forall a b. (a -> b) -> [a] -> [b]
map (PlinkPopNameMode -> EigenstratIndEntry -> PlinkFamEntry
eigenstratInd2PlinkFam PlinkPopNameMode
outPlinkPopMode) [EigenstratIndEntry]
eigenstratIndEntries)
[Char]
_ -> IO () -> Consumer (EigenstratSnpEntry, GenoLine) (SafeT IO) ()
forall a.
IO a -> Proxy () (EigenstratSnpEntry, GenoLine) () X (SafeT IO) a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> Consumer (EigenstratSnpEntry, GenoLine) (SafeT IO) ())
-> ([Char] -> IO ())
-> [Char]
-> Consumer (EigenstratSnpEntry, GenoLine) (SafeT IO) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PoseidonException -> IO ()
forall e a. Exception e => e -> IO a
throwIO (PoseidonException -> IO ())
-> ([Char] -> PoseidonException) -> [Char] -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> PoseidonException
PoseidonGenericException ([Char] -> Consumer (EigenstratSnpEntry, GenoLine) (SafeT IO) ())
-> [Char] -> Consumer (EigenstratSnpEntry, GenoLine) (SafeT IO) ()
forall a b. (a -> b) -> a -> b
$
[Char]
"Illegal outFormat " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
outFormat [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++
[Char]
". Only Outformats EIGENSTRAT or PLINK are allowed at the moment"
Effect (SafeT IO) () -> SafeT IO ()
forall (m :: * -> *) r. Monad m => Effect m r -> m r
runEffect (Effect (SafeT IO) () -> SafeT IO ())
-> Effect (SafeT IO) () -> SafeT IO ()
forall a b. (a -> b) -> a -> b
$ Producer (EigenstratSnpEntry, GenoLine) (SafeT IO) ()
eigenstratProd Producer (EigenstratSnpEntry, GenoLine) (SafeT IO) ()
-> Proxy
()
(EigenstratSnpEntry, GenoLine)
()
(EigenstratSnpEntry, GenoLine)
(SafeT IO)
()
-> Producer (EigenstratSnpEntry, GenoLine) (SafeT IO) ()
forall (m :: * -> *) a' a b r c' c.
Functor m =>
Proxy a' a () b m r -> Proxy () b c' c m r -> Proxy a' a c' c m r
>-> LogA
-> UTCTime
-> Proxy
()
(EigenstratSnpEntry, GenoLine)
()
(EigenstratSnpEntry, GenoLine)
(SafeT IO)
()
forall (m :: * -> *) a.
MonadIO m =>
LogA -> UTCTime -> Pipe a a m ()
printSNPCopyProgress LogA
logA UTCTime
currentTime Producer (EigenstratSnpEntry, GenoLine) (SafeT IO) ()
-> Consumer (EigenstratSnpEntry, GenoLine) (SafeT IO) ()
-> Effect (SafeT IO) ()
forall (m :: * -> *) a' a b r c' c.
Functor m =>
Proxy a' a () b m r -> Proxy () b c' c m r -> Proxy a' a c' c m r
>-> Consumer (EigenstratSnpEntry, GenoLine) (SafeT IO) ()
outConsumer
) (PoseidonException -> IO ()
forall e a. Exception e => e -> IO a
throwIO (PoseidonException -> IO ())
-> (SomeException -> PoseidonException) -> SomeException -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ErrorLength -> SomeException -> PoseidonException
PoseidonGenotypeExceptionForward ErrorLength
errLength)
IO () -> PoseidonIO ()
forall a. IO a -> ReaderT Env IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> PoseidonIO ()) -> IO () -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char] -> IO ()
renameFile ([Char]
outGabs [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
".gconvert" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
zipEnding) [Char]
outGabs
IO () -> PoseidonIO ()
forall a. IO a -> ReaderT Env IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> PoseidonIO ()) -> IO () -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char] -> IO ()
renameFile ([Char]
outSabs [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
".gconvert" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
zipEnding) [Char]
outSabs
IO () -> PoseidonIO ()
forall a. IO a -> ReaderT Env IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> PoseidonIO ()) -> IO () -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char] -> IO ()
renameFile ([Char]
outIabs [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
".gconvert") [Char]
outIabs
[Char] -> PoseidonIO ()
logInfo [Char]
"Done"
Bool -> PoseidonIO () -> PoseidonIO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Bool
onlyGeno Bool -> Bool -> Bool
|| Maybe [Char] -> Bool
forall a. Maybe a -> Bool
isJust Maybe [Char]
outPath) (PoseidonIO () -> PoseidonIO ()) -> PoseidonIO () -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ do
GenotypeFileSpec
gFileSpec <- case [Char]
outFormat of
[Char]
"EIGENSTRAT" -> GenotypeFileSpec -> ReaderT Env IO GenotypeFileSpec
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (GenotypeFileSpec -> ReaderT Env IO GenotypeFileSpec)
-> GenotypeFileSpec -> ReaderT Env IO GenotypeFileSpec
forall a b. (a -> b) -> a -> b
$
[Char]
-> Maybe [Char]
-> [Char]
-> Maybe [Char]
-> [Char]
-> Maybe [Char]
-> GenotypeFileSpec
GenotypeEigenstrat [Char]
outGrel Maybe [Char]
forall a. Maybe a
Nothing [Char]
outSrel Maybe [Char]
forall a. Maybe a
Nothing [Char]
outIrel Maybe [Char]
forall a. Maybe a
Nothing
[Char]
"PLINK" -> GenotypeFileSpec -> ReaderT Env IO GenotypeFileSpec
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (GenotypeFileSpec -> ReaderT Env IO GenotypeFileSpec)
-> GenotypeFileSpec -> ReaderT Env IO GenotypeFileSpec
forall a b. (a -> b) -> a -> b
$
[Char]
-> Maybe [Char]
-> [Char]
-> Maybe [Char]
-> [Char]
-> Maybe [Char]
-> GenotypeFileSpec
GenotypePlink [Char]
outGrel Maybe [Char]
forall a. Maybe a
Nothing [Char]
outSrel Maybe [Char]
forall a. Maybe a
Nothing [Char]
outIrel Maybe [Char]
forall a. Maybe a
Nothing
[Char]
_ -> IO GenotypeFileSpec -> ReaderT Env IO GenotypeFileSpec
forall a. IO a -> ReaderT Env IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO GenotypeFileSpec -> ReaderT Env IO GenotypeFileSpec)
-> ([Char] -> IO GenotypeFileSpec)
-> [Char]
-> ReaderT Env IO GenotypeFileSpec
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PoseidonException -> IO GenotypeFileSpec
forall e a. Exception e => e -> IO a
throwIO (PoseidonException -> IO GenotypeFileSpec)
-> ([Char] -> PoseidonException) -> [Char] -> IO GenotypeFileSpec
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> PoseidonException
PoseidonGenericException ([Char] -> ReaderT Env IO GenotypeFileSpec)
-> [Char] -> ReaderT Env IO GenotypeFileSpec
forall a b. (a -> b) -> a -> b
$
[Char]
"Illegal outFormat " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
outFormat [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++
[Char]
". Only Outformats EIGENSTRAT or PLINK are allowed at the moment"
let newGenotypeData :: GenotypeDataSpec
newGenotypeData = GenotypeFileSpec -> Maybe SNPSetSpec -> GenotypeDataSpec
GenotypeDataSpec GenotypeFileSpec
gFileSpec (GenotypeDataSpec -> Maybe SNPSetSpec
genotypeSnpSet (GenotypeDataSpec -> Maybe SNPSetSpec)
-> (PoseidonPackage -> GenotypeDataSpec)
-> PoseidonPackage
-> Maybe SNPSetSpec
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PoseidonPackage -> GenotypeDataSpec
posPacGenotypeData (PoseidonPackage -> Maybe SNPSetSpec)
-> PoseidonPackage -> Maybe SNPSetSpec
forall a b. (a -> b) -> a -> b
$ PoseidonPackage
pac)
newPac :: PoseidonPackage
newPac = PoseidonPackage
pac { posPacGenotypeData :: GenotypeDataSpec
posPacGenotypeData = GenotypeDataSpec
newGenotypeData }
[Char] -> PoseidonIO ()
logInfo ([Char] -> PoseidonIO ()) -> [Char] -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ [Char]
"Adjusting POSEIDON.yml for " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ PacNameAndVersion -> [Char]
forall a. Show a => a -> [Char]
show (PoseidonPackage -> PacNameAndVersion
posPacNameAndVersion PoseidonPackage
pac)
IO () -> PoseidonIO ()
forall a. IO a -> ReaderT Env IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> PoseidonIO ()) -> IO () -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ PoseidonPackage -> IO ()
writePoseidonPackage PoseidonPackage
newPac
Bool -> PoseidonIO () -> PoseidonIO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
removeOld (PoseidonIO () -> PoseidonIO ()) -> PoseidonIO () -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ do
let oldBaseDir :: [Char]
oldBaseDir = PoseidonPackage -> [Char]
posPacBaseDir PoseidonPackage
pac
[[Char]]
oldGenoFiles <- case GenotypeDataSpec -> GenotypeFileSpec
genotypeFileSpec (GenotypeDataSpec -> GenotypeFileSpec)
-> (PoseidonPackage -> GenotypeDataSpec)
-> PoseidonPackage
-> GenotypeFileSpec
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PoseidonPackage -> GenotypeDataSpec
posPacGenotypeData (PoseidonPackage -> GenotypeFileSpec)
-> PoseidonPackage -> GenotypeFileSpec
forall a b. (a -> b) -> a -> b
$ PoseidonPackage
pac of
GenotypeEigenstrat [Char]
g Maybe [Char]
_ [Char]
s Maybe [Char]
_ [Char]
i Maybe [Char]
_ -> [[Char]] -> ReaderT Env IO [[Char]]
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return [[Char]
oldBaseDir [Char] -> [Char] -> [Char]
</> [Char]
g, [Char]
oldBaseDir [Char] -> [Char] -> [Char]
</> [Char]
s, [Char]
oldBaseDir [Char] -> [Char] -> [Char]
</> [Char]
i]
GenotypePlink [Char]
g Maybe [Char]
_ [Char]
s Maybe [Char]
_ [Char]
i Maybe [Char]
_ -> [[Char]] -> ReaderT Env IO [[Char]]
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return [[Char]
oldBaseDir [Char] -> [Char] -> [Char]
</> [Char]
g, [Char]
oldBaseDir [Char] -> [Char] -> [Char]
</> [Char]
s, [Char]
oldBaseDir [Char] -> [Char] -> [Char]
</> [Char]
i]
GenotypeVCF [Char]
g Maybe [Char]
_ -> [[Char]] -> ReaderT Env IO [[Char]]
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return [[Char]
oldBaseDir [Char] -> [Char] -> [Char]
</> [Char]
g]
let newGenoFiles :: [[Char]]
newGenoFiles = [[Char]
outGabs, [Char]
outSabs, [Char]
outIabs]
let filesToDelete :: [[Char]]
filesToDelete = [[Char]]
oldGenoFiles [[Char]] -> [[Char]] -> [[Char]]
forall a. Eq a => [a] -> [a] -> [a]
\\ [[Char]]
newGenoFiles
IO () -> PoseidonIO ()
forall a. IO a -> ReaderT Env IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> PoseidonIO ())
-> ([[Char]] -> IO ()) -> [[Char]] -> PoseidonIO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Char] -> IO ()) -> [[Char]] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ [Char] -> IO ()
removeFile ([[Char]] -> PoseidonIO ()) -> [[Char]] -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ [[Char]]
filesToDelete
where
checkFile :: FilePath -> PoseidonIO Bool
checkFile :: [Char] -> ReaderT Env IO Bool
checkFile [Char]
fn = do
Bool
fe <- IO Bool -> ReaderT Env IO Bool
forall a. IO a -> ReaderT Env IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Bool -> ReaderT Env IO Bool) -> IO Bool -> ReaderT Env IO Bool
forall a b. (a -> b) -> a -> b
$ [Char] -> IO Bool
doesFileExist [Char]
fn
Bool -> PoseidonIO () -> PoseidonIO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
fe (PoseidonIO () -> PoseidonIO ()) -> PoseidonIO () -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ [Char] -> PoseidonIO ()
logWarning ([Char] -> PoseidonIO ()) -> [Char] -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ [Char]
"File " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
fn [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" exists"
Bool -> ReaderT Env IO Bool
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
fe