{-# LANGUAGE OverloadedStrings #-}
module Poseidon.CLI.Genoconvert where
import Poseidon.EntityTypes (HasNameAndVersion (..))
import Poseidon.GenotypeData (GenoDataSource (..),
GenotypeDataSpec (..),
GenotypeFileSpec (..),
GenotypeOutFormatSpec (..),
loadGenotypeData,
printSNPCopyProgress, writeVCF)
import Poseidon.Janno (JannoRows (..),
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 (forM_, 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,
takeExtension, (<.>), (</>))
data GenoconvertOptions = GenoconvertOptions
{ GenoconvertOptions -> [GenoDataSource]
_genoconvertGenoSources :: [GenoDataSource]
, GenoconvertOptions -> GenotypeOutFormatSpec
_genoConvertOutFormat :: GenotypeOutFormatSpec
, 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 GenotypeOutFormatSpec
outFormat Maybe [Char]
outPath
Bool
removeOld PlinkPopNameMode
outPlinkPopMode Bool
onlyLatest Bool
outZip) = do
let pacReadOpts :: PackageReadOptions
pacReadOpts = PackageReadOptions
defaultPackageReadOptions {
_readOptIgnoreChecksums = True
, _readOptIgnoreGeno = False
, _readOptGenoCheck = True
, _readOptOnlyLatest = 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_ (GenotypeOutFormatSpec
-> Bool
-> Maybe [Char]
-> Bool
-> PlinkPopNameMode
-> Bool
-> PoseidonPackage
-> PoseidonIO ()
convertGenoTo GenotypeOutFormatSpec
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_ (GenotypeOutFormatSpec
-> Bool
-> Maybe [Char]
-> Bool
-> PlinkPopNameMode
-> Bool
-> PoseidonPackage
-> PoseidonIO ()
convertGenoTo GenotypeOutFormatSpec
outFormat Bool
True Maybe [Char]
outPath Bool
removeOld PlinkPopNameMode
outPlinkPopMode Bool
outZip) [PoseidonPackage]
pseudoPackages
illegalFormatException :: String -> PoseidonException
illegalFormatException :: [Char] -> PoseidonException
illegalFormatException [Char]
outFormat = [Char] -> PoseidonException
PoseidonGenericException ([Char] -> PoseidonException) -> [Char] -> PoseidonException
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]
". Outformats can be EIGENSTRAT, PLINK or VCF"
convertGenoTo :: GenotypeOutFormatSpec -> Bool -> Maybe FilePath -> Bool ->
PlinkPopNameMode -> Bool -> PoseidonPackage -> PoseidonIO ()
convertGenoTo :: GenotypeOutFormatSpec
-> Bool
-> Maybe [Char]
-> Bool
-> PlinkPopNameMode
-> Bool
-> PoseidonPackage
-> PoseidonIO ()
convertGenoTo GenotypeOutFormatSpec
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]
++ GenotypeOutFormatSpec -> [Char]
forall a. Show a => a -> [Char]
show GenotypeOutFormatSpec
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]]
outFilesRel <- case GenotypeOutFormatSpec
outFormat of
GenotypeOutFormatSpec
GenotypeOutFormatEigenstrat -> [[Char]] -> ReaderT Env IO [[Char]]
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return
[[Char]
outName [Char] -> [Char] -> [Char]
<.> [Char]
"geno" [Char] -> [Char] -> [Char]
<.> [Char]
gz, [Char]
outName [Char] -> [Char] -> [Char]
<.> [Char]
"snp" [Char] -> [Char] -> [Char]
<.> [Char]
gz, [Char]
outName [Char] -> [Char] -> [Char]
<.> [Char]
"ind"]
GenotypeOutFormatSpec
GenotypeOutFormatPlink -> [[Char]] -> ReaderT Env IO [[Char]]
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return
[[Char]
outName [Char] -> [Char] -> [Char]
<.> [Char]
"bed" [Char] -> [Char] -> [Char]
<.> [Char]
gz, [Char]
outName [Char] -> [Char] -> [Char]
<.> [Char]
"bim" [Char] -> [Char] -> [Char]
<.> [Char]
gz, [Char]
outName [Char] -> [Char] -> [Char]
<.> [Char]
"fam"]
GenotypeOutFormatSpec
GenotypeOutFormatVCF -> [[Char]] -> ReaderT Env IO [[Char]]
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return
[[Char]
outName [Char] -> [Char] -> [Char]
<.> [Char]
"vcf" [Char] -> [Char] -> [Char]
<.> [Char]
gz]
[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 outFilesAbs :: [[Char]]
outFilesAbs = ([Char] -> [Char]) -> [[Char]] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map ([Char]
newBaseDir [Char] -> [Char] -> [Char]
</>) [[Char]]
outFilesRel
let outFilesAbsTemp :: [[Char]]
outFilesAbsTemp = do
[Char]
f <- [[Char]]
outFilesAbs
if [Char] -> [Char]
takeExtension [Char]
f [Char] -> [Char] -> Bool
forall a. Eq a => a -> a -> Bool
== [Char]
".gz" then
[Char] -> [[Char]]
forall a. a -> [a]
forall (m :: * -> *) a. Monad m => a -> m a
return ([Char] -> [[Char]]) -> [Char] -> [[Char]]
forall a b. (a -> b) -> a -> b
$ [Char]
f [Char] -> [Char] -> [Char]
<.> [Char]
"gconvert" [Char] -> [Char] -> [Char]
<.> [Char]
"gz"
else [Char] -> [[Char]]
forall a. a -> [a]
forall (m :: * -> *) a. Monad m => a -> m a
return ([Char] -> [[Char]]) -> [Char] -> [[Char]]
forall a b. (a -> b) -> a -> b
$ [Char]
f [Char] -> [Char] -> [Char]
<.> [Char]
"gconvert"
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]]
outFilesAbs
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 jannoRows :: [JannoRow]
jannoRows = JannoRows -> [JannoRow]
getJannoRows (JannoRows -> [JannoRow]) -> JannoRows -> [JannoRow]
forall a b. (a -> b) -> a -> b
$ PoseidonPackage -> JannoRows
posPacJanno 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
$ 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 GenotypeOutFormatSpec
outFormat of
GenotypeOutFormatSpec
GenotypeOutFormatEigenstrat -> [Char]
-> [Char]
-> [Char]
-> [EigenstratIndEntry]
-> Consumer (EigenstratSnpEntry, GenoLine) (SafeT IO) ()
forall (m :: * -> *).
MonadSafe m =>
[Char]
-> [Char]
-> [Char]
-> [EigenstratIndEntry]
-> Consumer (EigenstratSnpEntry, GenoLine) m ()
writeEigenstrat ([[Char]]
outFilesAbsTemp [[Char]] -> Int -> [Char]
forall a. HasCallStack => [a] -> Int -> a
!! Int
0)
([[Char]]
outFilesAbsTemp [[Char]] -> Int -> [Char]
forall a. HasCallStack => [a] -> Int -> a
!! Int
1)
([[Char]]
outFilesAbsTemp [[Char]] -> Int -> [Char]
forall a. HasCallStack => [a] -> Int -> a
!! Int
2)
[EigenstratIndEntry]
eigenstratIndEntries
GenotypeOutFormatSpec
GenotypeOutFormatPlink -> [Char]
-> [Char]
-> [Char]
-> [PlinkFamEntry]
-> Consumer (EigenstratSnpEntry, GenoLine) (SafeT IO) ()
forall (m :: * -> *).
MonadSafe m =>
[Char]
-> [Char]
-> [Char]
-> [PlinkFamEntry]
-> Consumer (EigenstratSnpEntry, GenoLine) m ()
writePlink ([[Char]]
outFilesAbsTemp [[Char]] -> Int -> [Char]
forall a. HasCallStack => [a] -> Int -> a
!! Int
0)
([[Char]]
outFilesAbsTemp [[Char]] -> Int -> [Char]
forall a. HasCallStack => [a] -> Int -> a
!! Int
1)
([[Char]]
outFilesAbsTemp [[Char]] -> Int -> [Char]
forall a. HasCallStack => [a] -> Int -> a
!! Int
2)
((EigenstratIndEntry -> PlinkFamEntry)
-> [EigenstratIndEntry] -> [PlinkFamEntry]
forall a b. (a -> b) -> [a] -> [b]
map (PlinkPopNameMode -> EigenstratIndEntry -> PlinkFamEntry
eigenstratInd2PlinkFam PlinkPopNameMode
outPlinkPopMode) [EigenstratIndEntry]
eigenstratIndEntries)
GenotypeOutFormatSpec
GenotypeOutFormatVCF -> LogA
-> [JannoRow]
-> [Char]
-> Consumer (EigenstratSnpEntry, GenoLine) (SafeT IO) ()
forall (m :: * -> *).
MonadSafe m =>
LogA
-> [JannoRow]
-> [Char]
-> Consumer (EigenstratSnpEntry, GenoLine) m ()
writeVCF LogA
logA [JannoRow]
jannoRows ([[Char]]
outFilesAbsTemp [[Char]] -> Int -> [Char]
forall a. HasCallStack => [a] -> Int -> a
!! Int
0)
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 ())
-> ((([Char], [Char]) -> IO ()) -> IO ())
-> (([Char], [Char]) -> IO ())
-> PoseidonIO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [([Char], [Char])] -> (([Char], [Char]) -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ ([[Char]] -> [[Char]] -> [([Char], [Char])]
forall a b. [a] -> [b] -> [(a, b)]
zip [[Char]]
outFilesAbs [[Char]]
outFilesAbsTemp) ((([Char], [Char]) -> IO ()) -> PoseidonIO ())
-> (([Char], [Char]) -> IO ()) -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ \([Char]
fn, [Char]
fnTemp) ->
[Char] -> [Char] -> IO ()
renameFile [Char]
fnTemp [Char]
fn
[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 GenotypeOutFormatSpec
outFormat of
GenotypeOutFormatSpec
GenotypeOutFormatEigenstrat -> 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]]
outFilesRel [[Char]] -> Int -> [Char]
forall a. HasCallStack => [a] -> Int -> a
!! Int
0) Maybe [Char]
forall a. Maybe a
Nothing ([[Char]]
outFilesRel [[Char]] -> Int -> [Char]
forall a. HasCallStack => [a] -> Int -> a
!! Int
1) Maybe [Char]
forall a. Maybe a
Nothing ([[Char]]
outFilesRel [[Char]] -> Int -> [Char]
forall a. HasCallStack => [a] -> Int -> a
!! Int
2) Maybe [Char]
forall a. Maybe a
Nothing
GenotypeOutFormatSpec
GenotypeOutFormatPlink -> 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]]
outFilesRel [[Char]] -> Int -> [Char]
forall a. HasCallStack => [a] -> Int -> a
!! Int
0) Maybe [Char]
forall a. Maybe a
Nothing ([[Char]]
outFilesRel [[Char]] -> Int -> [Char]
forall a. HasCallStack => [a] -> Int -> a
!! Int
1) Maybe [Char]
forall a. Maybe a
Nothing ([[Char]]
outFilesRel [[Char]] -> Int -> [Char]
forall a. HasCallStack => [a] -> Int -> a
!! Int
2) Maybe [Char]
forall a. Maybe a
Nothing
GenotypeOutFormatSpec
GenotypeOutFormatVCF -> 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] -> GenotypeFileSpec
GenotypeVCF ([[Char]]
outFilesRel [[Char]] -> Int -> [Char]
forall a. HasCallStack => [a] -> Int -> a
!! Int
0) Maybe [Char]
forall a. Maybe a
Nothing
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 = 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 filesToDelete :: [[Char]]
filesToDelete = [[Char]]
oldGenoFiles [[Char]] -> [[Char]] -> [[Char]]
forall a. Eq a => [a] -> [a] -> [a]
\\ [[Char]]
outFilesAbs
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