{-# LANGUAGE DeriveGeneric     #-}
{-# LANGUAGE LambdaCase        #-}
{-# LANGUAGE OverloadedStrings #-}

module Poseidon.Package (
    PoseidonYamlStruct (..),
    PoseidonPackage(..),
    PoseidonException(..),
    PackageReadOptions (..),
    findAllPoseidonYmlFiles,
    readPoseidonPackageCollection,
    readPoseidonPackageCollectionWithSkipIndicator,
    getJointGenotypeData,
    getJointJanno,
    getJointIndividualInfo,
    getExtendedIndividualInfo,
    newMinimalPackageTemplate,
    newPackageTemplate,
    renderMismatch,
    zipWithPadding,
    writePoseidonPackage,
    defaultPackageReadOptions,
    readPoseidonPackage,
    makePseudoPackageFromGenotypeData,
    getJannoRowsFromPac,
    packagesToPackageInfos,
    getAllGroupInfo,
    validateGeno,
    filterToRelevantPackages
) where

import           Poseidon.BibFile           (BibEntry (..), BibTeX,
                                             readBibTeXFile)
import           Poseidon.Contributor       (ContributorSpec (..))
import           Poseidon.EntityTypes       (EntitySpec, HasNameAndVersion (..),
                                             IndividualInfo (..),
                                             IndividualInfoCollection,
                                             PacNameAndVersion (..),
                                             determineRelevantPackages,
                                             isLatestInCollection,
                                             makePacNameAndVersion,
                                             renderNameWithVersion)
import           Poseidon.GenotypeData      (GenotypeDataSpec (..), joinEntries,
                                             loadGenotypeData, loadIndividuals,
                                             printSNPCopyProgress)
import           Poseidon.Janno             (JannoLibraryBuilt (..),
                                             JannoList (..), JannoRow (..),
                                             JannoRows (..), JannoSex (..),
                                             JannoUDG (..), createMinimalJanno,
                                             getMaybeJannoList,
                                             jannoHeaderString, readJannoFile)
import           Poseidon.PoseidonVersion   (asVersion, latestPoseidonVersion,
                                             showPoseidonVersion,
                                             validPoseidonVersions)
import           Poseidon.SequencingSource  (SSFLibraryBuilt (..), SSFUDG (..),
                                             SeqSourceRow (..),
                                             SeqSourceRows (..),
                                             readSeqSourceFile)
import           Poseidon.ServerClient      (AddJannoColSpec (..),
                                             ExtendedIndividualInfo (..),
                                             GroupInfo (..), PackageInfo (..))
import           Poseidon.Utils             (LogA, PoseidonException (..),
                                             PoseidonIO, checkFile,
                                             envErrorLength, envInputPlinkMode,
                                             envLogAction, logDebug, logError,
                                             logInfo, logWarning, logWithEnv,
                                             renderPoseidonException)

import           Control.DeepSeq            (($!!))
import           Control.Exception          (catch, throwIO)
import           Control.Monad              (filterM, forM, forM_, unless, void,
                                             when)
import           Control.Monad.Catch        (MonadThrow, throwM, try)
import           Control.Monad.IO.Class     (MonadIO, liftIO)
import           Data.Aeson                 (FromJSON, ToJSON, object,
                                             parseJSON, toJSON, withObject,
                                             (.!=), (.:), (.:?), (.=))
import qualified Data.ByteString            as B
import qualified Data.ByteString.Char8      as BSC
import           Data.Char                  (isSpace)
import           Data.Csv                   (toNamedRecord)
import           Data.Either                (lefts, rights)
import           Data.Function              (on)
import qualified Data.HashMap.Strict        as HM
import           Data.List                  (elemIndex, group, groupBy,
                                             intercalate, nub, sort, sortOn,
                                             (\\))
import           Data.Maybe                 (catMaybes, fromMaybe, isNothing,
                                             mapMaybe)
import           Data.Time                  (Day, UTCTime (..), getCurrentTime)
import qualified Data.Vector                as V
import           Data.Version               (Version (..), makeVersion)
import           Data.Yaml                  (decodeEither')
import           Data.Yaml.Pretty           (defConfig, encodePretty,
                                             setConfCompare, setConfDropNull)
import           GHC.Generics               (Generic)
import           Pipes                      (Pipe, Producer, cat, for,
                                             runEffect, yield, (>->))
import           Pipes.OrderedZip           (orderCheckPipe, orderedZip,
                                             orderedZipAll)
import qualified Pipes.Prelude              as P
import           Pipes.Safe                 (MonadSafe, runSafeT)
import           SequenceFormats.Eigenstrat (EigenstratIndEntry (..),
                                             EigenstratSnpEntry (..),
                                             GenoEntry (..), GenoLine,
                                             readEigenstratSnpFile)
import           SequenceFormats.Plink      (PlinkPopNameMode (..), readBimFile)
import           System.Directory           (doesDirectoryExist, listDirectory)
import           System.FilePath            (takeBaseName, takeDirectory,
                                             takeExtension, takeFileName, (</>))
import           System.IO                  (IOMode (ReadMode), hGetContents,
                                             withFile)

-- | Internal structure for YAML loading only
data PoseidonYamlStruct = PoseidonYamlStruct
    { PoseidonYamlStruct -> Version
_posYamlPoseidonVersion     :: Version
    , PoseidonYamlStruct -> FilePath
_posYamlTitle               :: String
    , PoseidonYamlStruct -> Maybe FilePath
_posYamlDescription         :: Maybe String
    , PoseidonYamlStruct -> [ContributorSpec]
_posYamlContributor         :: [ContributorSpec]
    , PoseidonYamlStruct -> Maybe Version
_posYamlPackageVersion      :: Maybe Version
    , PoseidonYamlStruct -> Maybe Day
_posYamlLastModified        :: Maybe Day
    , PoseidonYamlStruct -> GenotypeDataSpec
_posYamlGenotypeData        :: GenotypeDataSpec
    , PoseidonYamlStruct -> Maybe FilePath
_posYamlJannoFile           :: Maybe FilePath
    , PoseidonYamlStruct -> Maybe FilePath
_posYamlJannoFileChkSum     :: Maybe String
    , PoseidonYamlStruct -> Maybe FilePath
_posYamlSeqSourceFile       :: Maybe FilePath
    , PoseidonYamlStruct -> Maybe FilePath
_posYamlSeqSourceFileChkSum :: Maybe String
    , PoseidonYamlStruct -> Maybe FilePath
_posYamlBibFile             :: Maybe FilePath
    , PoseidonYamlStruct -> Maybe FilePath
_posYamlBibFileChkSum       :: Maybe String
    , PoseidonYamlStruct -> Maybe FilePath
_posYamlReadmeFile          :: Maybe FilePath
    , PoseidonYamlStruct -> Maybe FilePath
_posYamlChangelogFile       :: Maybe FilePath
    }
    deriving (Int -> PoseidonYamlStruct -> ShowS
[PoseidonYamlStruct] -> ShowS
PoseidonYamlStruct -> FilePath
(Int -> PoseidonYamlStruct -> ShowS)
-> (PoseidonYamlStruct -> FilePath)
-> ([PoseidonYamlStruct] -> ShowS)
-> Show PoseidonYamlStruct
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> PoseidonYamlStruct -> ShowS
showsPrec :: Int -> PoseidonYamlStruct -> ShowS
$cshow :: PoseidonYamlStruct -> FilePath
show :: PoseidonYamlStruct -> FilePath
$cshowList :: [PoseidonYamlStruct] -> ShowS
showList :: [PoseidonYamlStruct] -> ShowS
Show, PoseidonYamlStruct -> PoseidonYamlStruct -> Bool
(PoseidonYamlStruct -> PoseidonYamlStruct -> Bool)
-> (PoseidonYamlStruct -> PoseidonYamlStruct -> Bool)
-> Eq PoseidonYamlStruct
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PoseidonYamlStruct -> PoseidonYamlStruct -> Bool
== :: PoseidonYamlStruct -> PoseidonYamlStruct -> Bool
$c/= :: PoseidonYamlStruct -> PoseidonYamlStruct -> Bool
/= :: PoseidonYamlStruct -> PoseidonYamlStruct -> Bool
Eq, (forall x. PoseidonYamlStruct -> Rep PoseidonYamlStruct x)
-> (forall x. Rep PoseidonYamlStruct x -> PoseidonYamlStruct)
-> Generic PoseidonYamlStruct
forall x. Rep PoseidonYamlStruct x -> PoseidonYamlStruct
forall x. PoseidonYamlStruct -> Rep PoseidonYamlStruct x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. PoseidonYamlStruct -> Rep PoseidonYamlStruct x
from :: forall x. PoseidonYamlStruct -> Rep PoseidonYamlStruct x
$cto :: forall x. Rep PoseidonYamlStruct x -> PoseidonYamlStruct
to :: forall x. Rep PoseidonYamlStruct x -> PoseidonYamlStruct
Generic)

poseidonJannoFilePath :: FilePath -> PoseidonYamlStruct -> Maybe FilePath
poseidonJannoFilePath :: FilePath -> PoseidonYamlStruct -> Maybe FilePath
poseidonJannoFilePath FilePath
baseDir PoseidonYamlStruct
yml = (FilePath
baseDir FilePath -> ShowS
</>) ShowS -> Maybe FilePath -> Maybe FilePath
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> PoseidonYamlStruct -> Maybe FilePath
_posYamlJannoFile PoseidonYamlStruct
yml
poseidonSeqSourceFilePath :: FilePath -> PoseidonYamlStruct -> Maybe FilePath
poseidonSeqSourceFilePath :: FilePath -> PoseidonYamlStruct -> Maybe FilePath
poseidonSeqSourceFilePath FilePath
baseDir PoseidonYamlStruct
yml = (FilePath
baseDir FilePath -> ShowS
</>) ShowS -> Maybe FilePath -> Maybe FilePath
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> PoseidonYamlStruct -> Maybe FilePath
_posYamlSeqSourceFile PoseidonYamlStruct
yml
poseidonBibFilePath :: FilePath -> PoseidonYamlStruct -> Maybe FilePath
poseidonBibFilePath :: FilePath -> PoseidonYamlStruct -> Maybe FilePath
poseidonBibFilePath FilePath
baseDir PoseidonYamlStruct
yml = (FilePath
baseDir FilePath -> ShowS
</>) ShowS -> Maybe FilePath -> Maybe FilePath
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> PoseidonYamlStruct -> Maybe FilePath
_posYamlBibFile PoseidonYamlStruct
yml
poseidonReadmeFilePath :: FilePath -> PoseidonYamlStruct -> Maybe FilePath
poseidonReadmeFilePath :: FilePath -> PoseidonYamlStruct -> Maybe FilePath
poseidonReadmeFilePath FilePath
baseDir PoseidonYamlStruct
yml = (FilePath
baseDir FilePath -> ShowS
</>) ShowS -> Maybe FilePath -> Maybe FilePath
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> PoseidonYamlStruct -> Maybe FilePath
_posYamlReadmeFile PoseidonYamlStruct
yml
poseidonChangelogFilePath :: FilePath -> PoseidonYamlStruct -> Maybe FilePath
poseidonChangelogFilePath :: FilePath -> PoseidonYamlStruct -> Maybe FilePath
poseidonChangelogFilePath FilePath
baseDir PoseidonYamlStruct
yml = (FilePath
baseDir FilePath -> ShowS
</>) ShowS -> Maybe FilePath -> Maybe FilePath
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> PoseidonYamlStruct -> Maybe FilePath
_posYamlChangelogFile PoseidonYamlStruct
yml

instance FromJSON PoseidonYamlStruct where
    parseJSON :: Value -> Parser PoseidonYamlStruct
parseJSON = FilePath
-> (Object -> Parser PoseidonYamlStruct)
-> Value
-> Parser PoseidonYamlStruct
forall a. FilePath -> (Object -> Parser a) -> Value -> Parser a
withObject FilePath
"PoseidonYamlStruct" ((Object -> Parser PoseidonYamlStruct)
 -> Value -> Parser PoseidonYamlStruct)
-> (Object -> Parser PoseidonYamlStruct)
-> Value
-> Parser PoseidonYamlStruct
forall a b. (a -> b) -> a -> b
$ \Object
v -> Version
-> FilePath
-> Maybe FilePath
-> [ContributorSpec]
-> Maybe Version
-> Maybe Day
-> GenotypeDataSpec
-> Maybe FilePath
-> Maybe FilePath
-> Maybe FilePath
-> Maybe FilePath
-> Maybe FilePath
-> Maybe FilePath
-> Maybe FilePath
-> Maybe FilePath
-> PoseidonYamlStruct
PoseidonYamlStruct
        (Version
 -> FilePath
 -> Maybe FilePath
 -> [ContributorSpec]
 -> Maybe Version
 -> Maybe Day
 -> GenotypeDataSpec
 -> Maybe FilePath
 -> Maybe FilePath
 -> Maybe FilePath
 -> Maybe FilePath
 -> Maybe FilePath
 -> Maybe FilePath
 -> Maybe FilePath
 -> Maybe FilePath
 -> PoseidonYamlStruct)
-> Parser Version
-> Parser
     (FilePath
      -> Maybe FilePath
      -> [ContributorSpec]
      -> Maybe Version
      -> Maybe Day
      -> GenotypeDataSpec
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> PoseidonYamlStruct)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
v Object -> Key -> Parser Version
forall a. FromJSON a => Object -> Key -> Parser a
.:   Key
"poseidonVersion"
        Parser
  (FilePath
   -> Maybe FilePath
   -> [ContributorSpec]
   -> Maybe Version
   -> Maybe Day
   -> GenotypeDataSpec
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> PoseidonYamlStruct)
-> Parser FilePath
-> Parser
     (Maybe FilePath
      -> [ContributorSpec]
      -> Maybe Version
      -> Maybe Day
      -> GenotypeDataSpec
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> PoseidonYamlStruct)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Key -> Parser FilePath
forall a. FromJSON a => Object -> Key -> Parser a
.:   Key
"title"
        Parser
  (Maybe FilePath
   -> [ContributorSpec]
   -> Maybe Version
   -> Maybe Day
   -> GenotypeDataSpec
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> PoseidonYamlStruct)
-> Parser (Maybe FilePath)
-> Parser
     ([ContributorSpec]
      -> Maybe Version
      -> Maybe Day
      -> GenotypeDataSpec
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> PoseidonYamlStruct)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Key -> Parser (Maybe FilePath)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:?  Key
"description"
        Parser
  ([ContributorSpec]
   -> Maybe Version
   -> Maybe Day
   -> GenotypeDataSpec
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> PoseidonYamlStruct)
-> Parser [ContributorSpec]
-> Parser
     (Maybe Version
      -> Maybe Day
      -> GenotypeDataSpec
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> PoseidonYamlStruct)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Key -> Parser (Maybe [ContributorSpec])
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:?  Key
"contributor" Parser (Maybe [ContributorSpec])
-> [ContributorSpec] -> Parser [ContributorSpec]
forall a. Parser (Maybe a) -> a -> Parser a
.!= []
        Parser
  (Maybe Version
   -> Maybe Day
   -> GenotypeDataSpec
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> PoseidonYamlStruct)
-> Parser (Maybe Version)
-> Parser
     (Maybe Day
      -> GenotypeDataSpec
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> PoseidonYamlStruct)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Key -> Parser (Maybe Version)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:?  Key
"packageVersion"
        Parser
  (Maybe Day
   -> GenotypeDataSpec
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> PoseidonYamlStruct)
-> Parser (Maybe Day)
-> Parser
     (GenotypeDataSpec
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> PoseidonYamlStruct)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Key -> Parser (Maybe Day)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:?  Key
"lastModified"
        Parser
  (GenotypeDataSpec
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> PoseidonYamlStruct)
-> Parser GenotypeDataSpec
-> Parser
     (Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> PoseidonYamlStruct)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Key -> Parser GenotypeDataSpec
forall a. FromJSON a => Object -> Key -> Parser a
.:   Key
"genotypeData"
        Parser
  (Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> PoseidonYamlStruct)
-> Parser (Maybe FilePath)
-> Parser
     (Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> PoseidonYamlStruct)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Key -> Parser (Maybe FilePath)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:?  Key
"jannoFile"
        Parser
  (Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> PoseidonYamlStruct)
-> Parser (Maybe FilePath)
-> Parser
     (Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> PoseidonYamlStruct)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Key -> Parser (Maybe FilePath)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:?  Key
"jannoFileChkSum"
        Parser
  (Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> PoseidonYamlStruct)
-> Parser (Maybe FilePath)
-> Parser
     (Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> PoseidonYamlStruct)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Key -> Parser (Maybe FilePath)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:?  Key
"sequencingSourceFile"
        Parser
  (Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> PoseidonYamlStruct)
-> Parser (Maybe FilePath)
-> Parser
     (Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> Maybe FilePath
      -> PoseidonYamlStruct)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Key -> Parser (Maybe FilePath)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:?  Key
"sequencingSourceFileChkSum"
        Parser
  (Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> Maybe FilePath
   -> PoseidonYamlStruct)
-> Parser (Maybe FilePath)
-> Parser
     (Maybe FilePath
      -> Maybe FilePath -> Maybe FilePath -> PoseidonYamlStruct)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Key -> Parser (Maybe FilePath)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:?  Key
"bibFile"
        Parser
  (Maybe FilePath
   -> Maybe FilePath -> Maybe FilePath -> PoseidonYamlStruct)
-> Parser (Maybe FilePath)
-> Parser (Maybe FilePath -> Maybe FilePath -> PoseidonYamlStruct)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Key -> Parser (Maybe FilePath)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:?  Key
"bibFileChkSum"
        Parser (Maybe FilePath -> Maybe FilePath -> PoseidonYamlStruct)
-> Parser (Maybe FilePath)
-> Parser (Maybe FilePath -> PoseidonYamlStruct)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Key -> Parser (Maybe FilePath)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:?  Key
"readmeFile"
        Parser (Maybe FilePath -> PoseidonYamlStruct)
-> Parser (Maybe FilePath) -> Parser PoseidonYamlStruct
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Key -> Parser (Maybe FilePath)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:?  Key
"changelogFile"

instance ToJSON PoseidonYamlStruct where
    toJSON :: PoseidonYamlStruct -> Value
toJSON PoseidonYamlStruct
x = [Pair] -> Value
object ([Pair] -> Value) -> [Pair] -> Value
forall a b. (a -> b) -> a -> b
$ [
        Key
"poseidonVersion" Key -> Version -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= PoseidonYamlStruct -> Version
_posYamlPoseidonVersion PoseidonYamlStruct
x,
        Key
"title"           Key -> FilePath -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= PoseidonYamlStruct -> FilePath
_posYamlTitle PoseidonYamlStruct
x,
        Key
"description"     Key -> Maybe FilePath -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= PoseidonYamlStruct -> Maybe FilePath
_posYamlDescription PoseidonYamlStruct
x] [Pair] -> [Pair] -> [Pair]
forall a. [a] -> [a] -> [a]
++
        (if Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ [ContributorSpec] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null (PoseidonYamlStruct -> [ContributorSpec]
_posYamlContributor PoseidonYamlStruct
x) then [Key
"contributor" Key -> [ContributorSpec] -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= PoseidonYamlStruct -> [ContributorSpec]
_posYamlContributor PoseidonYamlStruct
x] else []) [Pair] -> [Pair] -> [Pair]
forall a. [a] -> [a] -> [a]
++
        [Key
"packageVersion"  Key -> Maybe Version -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= PoseidonYamlStruct -> Maybe Version
_posYamlPackageVersion PoseidonYamlStruct
x,
        Key
"lastModified"    Key -> Maybe Day -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= PoseidonYamlStruct -> Maybe Day
_posYamlLastModified PoseidonYamlStruct
x,
        Key
"genotypeData"    Key -> GenotypeDataSpec -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= PoseidonYamlStruct -> GenotypeDataSpec
_posYamlGenotypeData PoseidonYamlStruct
x,
        Key
"jannoFile"       Key -> Maybe FilePath -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= PoseidonYamlStruct -> Maybe FilePath
_posYamlJannoFile PoseidonYamlStruct
x,
        Key
"jannoFileChkSum" Key -> Maybe FilePath -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= PoseidonYamlStruct -> Maybe FilePath
_posYamlJannoFileChkSum PoseidonYamlStruct
x,
        Key
"sequencingSourceFile"       Key -> Maybe FilePath -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= PoseidonYamlStruct -> Maybe FilePath
_posYamlSeqSourceFile PoseidonYamlStruct
x,
        Key
"sequencingSourceFileChkSum" Key -> Maybe FilePath -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= PoseidonYamlStruct -> Maybe FilePath
_posYamlSeqSourceFileChkSum PoseidonYamlStruct
x,
        Key
"bibFile"         Key -> Maybe FilePath -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= PoseidonYamlStruct -> Maybe FilePath
_posYamlBibFile PoseidonYamlStruct
x,
        Key
"bibFileChkSum"   Key -> Maybe FilePath -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= PoseidonYamlStruct -> Maybe FilePath
_posYamlBibFileChkSum PoseidonYamlStruct
x,
        Key
"readmeFile"      Key -> Maybe FilePath -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= PoseidonYamlStruct -> Maybe FilePath
_posYamlReadmeFile PoseidonYamlStruct
x,
        Key
"changelogFile"   Key -> Maybe FilePath -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= PoseidonYamlStruct -> Maybe FilePath
_posYamlChangelogFile PoseidonYamlStruct
x
        ]

instance HasNameAndVersion PoseidonYamlStruct where
    getPacName :: PoseidonYamlStruct -> FilePath
getPacName     = PoseidonYamlStruct -> FilePath
_posYamlTitle
    getPacVersion :: PoseidonYamlStruct -> Maybe Version
getPacVersion  = PoseidonYamlStruct -> Maybe Version
_posYamlPackageVersion

-- | A data type to represent a Poseidon Package
data PoseidonPackage = PoseidonPackage
    { PoseidonPackage -> FilePath
posPacBaseDir             :: FilePath
    -- ^ the base directory of the YAML file
    , PoseidonPackage -> Version
posPacPoseidonVersion     :: Version
    -- ^ the version of the package
    , PoseidonPackage -> PacNameAndVersion
posPacNameAndVersion      :: PacNameAndVersion
    -- ^ the title and version of the package
    , PoseidonPackage -> Maybe FilePath
posPacDescription         :: Maybe String
    -- ^ the optional description string of the package
    , PoseidonPackage -> [ContributorSpec]
posPacContributor         :: [ContributorSpec]
    -- ^ the contributor(s) of the package
    , PoseidonPackage -> Maybe Day
posPacLastModified        :: Maybe Day
    -- ^ the optional date of last update
    , PoseidonPackage -> GenotypeDataSpec
posPacGenotypeData        :: GenotypeDataSpec
    -- ^ the paths to the genotype files
    , PoseidonPackage -> Maybe FilePath
posPacJannoFile           :: Maybe FilePath
    -- ^ the path to the janno file
    , PoseidonPackage -> JannoRows
posPacJanno               :: JannoRows
    -- ^ the loaded janno file
    , PoseidonPackage -> Maybe FilePath
posPacJannoFileChkSum     :: Maybe String
    -- ^ the optional jannofile checksum
    , PoseidonPackage -> Maybe FilePath
posPacSeqSourceFile       :: Maybe FilePath
    -- ^ the path to the seqSource file
    , PoseidonPackage -> SeqSourceRows
posPacSeqSource           :: SeqSourceRows
    -- ^ the loaded seqSource file
    , PoseidonPackage -> Maybe FilePath
posPacSeqSourceFileChkSum :: Maybe String
    -- ^ the optional seqSource file checksum
    , PoseidonPackage -> Maybe FilePath
posPacBibFile             :: Maybe FilePath
    -- ^ the path to the BibTeX file
    , PoseidonPackage -> BibTeX
posPacBib                 :: BibTeX
    -- ^ the loaded bibliography file
    , PoseidonPackage -> Maybe FilePath
posPacBibFileChkSum       :: Maybe String
    -- ^ the optional bibfile chksum
    , PoseidonPackage -> Maybe FilePath
posPacReadmeFile          :: Maybe FilePath
    -- ^ the path to the README file
    , PoseidonPackage -> Maybe FilePath
posPacChangelogFile       :: Maybe FilePath
    -- ^ the path to the CHANGELOG file
    }
    deriving (Int -> PoseidonPackage -> ShowS
[PoseidonPackage] -> ShowS
PoseidonPackage -> FilePath
(Int -> PoseidonPackage -> ShowS)
-> (PoseidonPackage -> FilePath)
-> ([PoseidonPackage] -> ShowS)
-> Show PoseidonPackage
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> PoseidonPackage -> ShowS
showsPrec :: Int -> PoseidonPackage -> ShowS
$cshow :: PoseidonPackage -> FilePath
show :: PoseidonPackage -> FilePath
$cshowList :: [PoseidonPackage] -> ShowS
showList :: [PoseidonPackage] -> ShowS
Show, PoseidonPackage -> PoseidonPackage -> Bool
(PoseidonPackage -> PoseidonPackage -> Bool)
-> (PoseidonPackage -> PoseidonPackage -> Bool)
-> Eq PoseidonPackage
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PoseidonPackage -> PoseidonPackage -> Bool
== :: PoseidonPackage -> PoseidonPackage -> Bool
$c/= :: PoseidonPackage -> PoseidonPackage -> Bool
/= :: PoseidonPackage -> PoseidonPackage -> Bool
Eq, (forall x. PoseidonPackage -> Rep PoseidonPackage x)
-> (forall x. Rep PoseidonPackage x -> PoseidonPackage)
-> Generic PoseidonPackage
forall x. Rep PoseidonPackage x -> PoseidonPackage
forall x. PoseidonPackage -> Rep PoseidonPackage x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. PoseidonPackage -> Rep PoseidonPackage x
from :: forall x. PoseidonPackage -> Rep PoseidonPackage x
$cto :: forall x. Rep PoseidonPackage x -> PoseidonPackage
to :: forall x. Rep PoseidonPackage x -> PoseidonPackage
Generic)

instance Ord PoseidonPackage where
    compare :: PoseidonPackage -> PoseidonPackage -> Ordering
compare PoseidonPackage
pacA PoseidonPackage
pacB = (FilePath, Maybe Version) -> (FilePath, Maybe Version) -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (PoseidonPackage -> FilePath
forall a. HasNameAndVersion a => a -> FilePath
getPacName PoseidonPackage
pacA, PoseidonPackage -> Maybe Version
forall a. HasNameAndVersion a => a -> Maybe Version
getPacVersion PoseidonPackage
pacA) (PoseidonPackage -> FilePath
forall a. HasNameAndVersion a => a -> FilePath
getPacName PoseidonPackage
pacB, PoseidonPackage -> Maybe Version
forall a. HasNameAndVersion a => a -> Maybe Version
getPacVersion PoseidonPackage
pacB)

instance HasNameAndVersion PoseidonPackage where
    getPacName :: PoseidonPackage -> FilePath
getPacName = PacNameAndVersion -> FilePath
forall a. HasNameAndVersion a => a -> FilePath
getPacName (PacNameAndVersion -> FilePath)
-> (PoseidonPackage -> PacNameAndVersion)
-> PoseidonPackage
-> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PoseidonPackage -> PacNameAndVersion
posPacNameAndVersion
    getPacVersion :: PoseidonPackage -> Maybe Version
getPacVersion = PacNameAndVersion -> Maybe Version
forall a. HasNameAndVersion a => a -> Maybe Version
getPacVersion (PacNameAndVersion -> Maybe Version)
-> (PoseidonPackage -> PacNameAndVersion)
-> PoseidonPackage
-> Maybe Version
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PoseidonPackage -> PacNameAndVersion
posPacNameAndVersion

data PackageReadOptions = PackageReadOptions
    { PackageReadOptions -> Bool
_readOptIgnoreChecksums  :: Bool
    -- ^ whether to ignore all checksums
    , PackageReadOptions -> Bool
_readOptIgnoreGeno       :: Bool
    -- ^ whether to ignore missing genotype files, useful for developer use cases
    , PackageReadOptions -> Bool
_readOptGenoCheck        :: Bool
    -- ^ whether to check the SNPs of the genotypes
    , PackageReadOptions -> Bool
_readOptFullGeno         :: Bool
    -- ^ whether to check all SNPs or only the first 100
    , PackageReadOptions -> Bool
_readOptIgnorePosVersion :: Bool
    -- ^ whether to ignore the Poseidon version of an input package.
    , PackageReadOptions -> Bool
_readOptOnlyLatest       :: Bool
    -- ^ whether to keep multiple versions of the same package (True) or just the latest one (False)
    }

-- Even though PlinkPopNameAsFamily is a sensible default, I would like to force the API to demand this explicitly
-- from the client caller, since we typically get this as an option from the CLI, and it would be wrong not to explicitly
-- pass it on to the package read system.
defaultPackageReadOptions :: PackageReadOptions
defaultPackageReadOptions :: PackageReadOptions
defaultPackageReadOptions = PackageReadOptions {
      _readOptIgnoreChecksums :: Bool
_readOptIgnoreChecksums      = Bool
False
    , _readOptIgnoreGeno :: Bool
_readOptIgnoreGeno           = Bool
False
    , _readOptGenoCheck :: Bool
_readOptGenoCheck            = Bool
True
    , _readOptFullGeno :: Bool
_readOptFullGeno             = Bool
False
    , _readOptIgnorePosVersion :: Bool
_readOptIgnorePosVersion     = Bool
False
    , _readOptOnlyLatest :: Bool
_readOptOnlyLatest           = Bool
False
    }

readPoseidonPackageCollection :: PackageReadOptions
                              -> [FilePath] -- ^ A list of base directories where to search in
                              -> PoseidonIO [PoseidonPackage] -- ^ A list of returned poseidon packages
readPoseidonPackageCollection :: PackageReadOptions -> [FilePath] -> PoseidonIO [PoseidonPackage]
readPoseidonPackageCollection PackageReadOptions
opts [FilePath]
baseDirs = ([PoseidonPackage], Bool) -> [PoseidonPackage]
forall a b. (a, b) -> a
fst (([PoseidonPackage], Bool) -> [PoseidonPackage])
-> ReaderT Env IO ([PoseidonPackage], Bool)
-> PoseidonIO [PoseidonPackage]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> PackageReadOptions
-> [FilePath] -> ReaderT Env IO ([PoseidonPackage], Bool)
readPoseidonPackageCollectionWithSkipIndicator PackageReadOptions
opts [FilePath]
baseDirs

-- | a utility function to load all poseidon packages found recursively in multiple base directories.
-- This also takes care of smart filtering and duplication checks. Exceptions lead to skipping packages and outputting
-- warnings. A flag is returned for whether packages were skipped (needed for validate)
readPoseidonPackageCollectionWithSkipIndicator :: PackageReadOptions
                              -> [FilePath] -- ^ A list of base directories where to search in
                              -> PoseidonIO ([PoseidonPackage], Bool) -- ^ A list of returned poseidon packages and a flag for whether packages were skipped
readPoseidonPackageCollectionWithSkipIndicator :: PackageReadOptions
-> [FilePath] -> ReaderT Env IO ([PoseidonPackage], Bool)
readPoseidonPackageCollectionWithSkipIndicator PackageReadOptions
opts [FilePath]
baseDirs = do
    FilePath -> PoseidonIO ()
logInfo FilePath
"Checking base directories... "
    [FilePath]
goodDirs <- [Maybe FilePath] -> [FilePath]
forall a. [Maybe a] -> [a]
catMaybes ([Maybe FilePath] -> [FilePath])
-> ReaderT Env IO [Maybe FilePath] -> ReaderT Env IO [FilePath]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (FilePath -> ReaderT Env IO (Maybe FilePath))
-> [FilePath] -> ReaderT Env IO [Maybe FilePath]
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 FilePath -> ReaderT Env IO (Maybe FilePath)
checkIfBaseDirExists [FilePath]
baseDirs
    FilePath -> PoseidonIO ()
logInfo FilePath
"Searching POSEIDON.yml files... "
    [FilePath]
posFilesAllVersions <- IO [FilePath] -> ReaderT Env IO [FilePath]
forall a. IO a -> ReaderT Env IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO [FilePath] -> ReaderT Env IO [FilePath])
-> IO [FilePath] -> ReaderT Env IO [FilePath]
forall a b. (a -> b) -> a -> b
$ [[FilePath]] -> [FilePath]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[FilePath]] -> [FilePath]) -> IO [[FilePath]] -> IO [FilePath]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (FilePath -> IO [FilePath]) -> [FilePath] -> IO [[FilePath]]
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 FilePath -> IO [FilePath]
findAllPoseidonYmlFiles [FilePath]
goodDirs
    FilePath -> PoseidonIO ()
logInfo (FilePath -> PoseidonIO ()) -> FilePath -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ Int -> FilePath
forall a. Show a => a -> FilePath
show ([FilePath] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [FilePath]
posFilesAllVersions) FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ FilePath
" found"
    [FilePath]
posFiles <- if PackageReadOptions -> Bool
_readOptIgnorePosVersion PackageReadOptions
opts
                then [FilePath] -> ReaderT Env IO [FilePath]
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return [FilePath]
posFilesAllVersions
                else do
                    FilePath -> PoseidonIO ()
logInfo FilePath
"Checking Poseidon versions... "
                    [FilePath] -> ReaderT Env IO [FilePath]
filterByPoseidonVersion [FilePath]
posFilesAllVersions
    FilePath -> PoseidonIO ()
logInfo FilePath
"Initializing packages... "
    [Either PoseidonException PoseidonPackage]
eitherPackages <- ((Integer, FilePath)
 -> ReaderT Env IO (Either PoseidonException PoseidonPackage))
-> [(Integer, FilePath)]
-> ReaderT Env IO [Either PoseidonException 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 (Integer, FilePath)
-> ReaderT Env IO (Either PoseidonException PoseidonPackage)
tryDecodePoseidonPackage ([(Integer, FilePath)]
 -> ReaderT Env IO [Either PoseidonException PoseidonPackage])
-> [(Integer, FilePath)]
-> ReaderT Env IO [Either PoseidonException PoseidonPackage]
forall a b. (a -> b) -> a -> b
$ [Integer] -> [FilePath] -> [(Integer, FilePath)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Integer
1..] [FilePath]
posFiles
    -- notifying the users of package problems
    Bool
skipIndicator <- if ([PoseidonException] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null ([PoseidonException] -> Bool)
-> ([Either PoseidonException PoseidonPackage]
    -> [PoseidonException])
-> [Either PoseidonException PoseidonPackage]
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Either PoseidonException PoseidonPackage] -> [PoseidonException]
forall a b. [Either a b] -> [a]
lefts ([Either PoseidonException PoseidonPackage] -> Bool)
-> [Either PoseidonException PoseidonPackage] -> Bool
forall a b. (a -> b) -> a -> b
$ [Either PoseidonException PoseidonPackage]
eitherPackages) then Bool -> ReaderT Env IO Bool
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False else do
        FilePath -> PoseidonIO ()
logWarning FilePath
"Some packages were skipped due to issues:"
        [(FilePath, Either PoseidonException PoseidonPackage)]
-> ((FilePath, Either PoseidonException PoseidonPackage)
    -> PoseidonIO ())
-> PoseidonIO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ ([FilePath]
-> [Either PoseidonException PoseidonPackage]
-> [(FilePath, Either PoseidonException PoseidonPackage)]
forall a b. [a] -> [b] -> [(a, b)]
zip [FilePath]
posFiles [Either PoseidonException PoseidonPackage]
eitherPackages) (((FilePath, Either PoseidonException PoseidonPackage)
  -> PoseidonIO ())
 -> PoseidonIO ())
-> ((FilePath, Either PoseidonException PoseidonPackage)
    -> PoseidonIO ())
-> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ \(FilePath
posF, Either PoseidonException PoseidonPackage
epac) -> do
            case Either PoseidonException PoseidonPackage
epac of
                Left PoseidonException
e -> do
                    FilePath -> PoseidonIO ()
logWarning (FilePath -> PoseidonIO ()) -> FilePath -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ FilePath
"In the package described in " FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ FilePath
posF FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ FilePath
":"
                    FilePath -> PoseidonIO ()
logWarning (FilePath -> PoseidonIO ()) -> FilePath -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ PoseidonException -> FilePath
renderPoseidonException PoseidonException
e
                Either PoseidonException PoseidonPackage
_ -> () -> PoseidonIO ()
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
        Bool -> ReaderT Env IO Bool
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
    let loadedPackages :: [PoseidonPackage]
loadedPackages = [Either PoseidonException PoseidonPackage] -> [PoseidonPackage]
forall a b. [Either a b] -> [b]
rights [Either PoseidonException PoseidonPackage]
eitherPackages
    -- filter the package list to only latest packages, if this is requested
    [PoseidonPackage]
filteredPackageList <-
            if PackageReadOptions -> Bool
_readOptOnlyLatest PackageReadOptions
opts
            then (PoseidonPackage -> ReaderT Env IO Bool)
-> [PoseidonPackage] -> PoseidonIO [PoseidonPackage]
forall (m :: * -> *) a.
Applicative m =>
(a -> m Bool) -> [a] -> m [a]
filterM ([PoseidonPackage] -> PoseidonPackage -> ReaderT Env IO Bool
forall (m :: * -> *) a.
(MonadThrow m, HasNameAndVersion a) =>
[a] -> a -> m Bool
isLatestInCollection [PoseidonPackage]
loadedPackages) [PoseidonPackage]
loadedPackages
            else [PoseidonPackage] -> PoseidonIO [PoseidonPackage]
forall a. a -> ReaderT Env IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([PoseidonPackage] -> PoseidonIO [PoseidonPackage])
-> [PoseidonPackage] -> PoseidonIO [PoseidonPackage]
forall a b. (a -> b) -> a -> b
$ [PoseidonPackage]
loadedPackages
    -- check if any packages appear more than once
    let duplicateGroups :: [[PoseidonPackage]]
duplicateGroups =   ([PoseidonPackage] -> Bool)
-> [[PoseidonPackage]] -> [[PoseidonPackage]]
forall a. (a -> Bool) -> [a] -> [a]
filter ((Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>Int
1) (Int -> Bool)
-> ([PoseidonPackage] -> Int) -> [PoseidonPackage] -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [PoseidonPackage] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length)
                          ([[PoseidonPackage]] -> [[PoseidonPackage]])
-> ([PoseidonPackage] -> [[PoseidonPackage]])
-> [PoseidonPackage]
-> [[PoseidonPackage]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (PoseidonPackage -> PoseidonPackage -> Bool)
-> [PoseidonPackage] -> [[PoseidonPackage]]
forall a. (a -> a -> Bool) -> [a] -> [[a]]
groupBy (\PoseidonPackage
a PoseidonPackage
b -> PoseidonPackage -> PacNameAndVersion
forall a. HasNameAndVersion a => a -> PacNameAndVersion
makePacNameAndVersion PoseidonPackage
a PacNameAndVersion -> PacNameAndVersion -> Bool
forall a. Eq a => a -> a -> Bool
== PoseidonPackage -> PacNameAndVersion
forall a. HasNameAndVersion a => a -> PacNameAndVersion
makePacNameAndVersion PoseidonPackage
b)
                          ([PoseidonPackage] -> [[PoseidonPackage]])
-> ([PoseidonPackage] -> [PoseidonPackage])
-> [PoseidonPackage]
-> [[PoseidonPackage]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (PoseidonPackage -> PacNameAndVersion)
-> [PoseidonPackage] -> [PoseidonPackage]
forall b a. Ord b => (a -> b) -> [a] -> [a]
sortOn PoseidonPackage -> PacNameAndVersion
forall a. HasNameAndVersion a => a -> PacNameAndVersion
makePacNameAndVersion ([PoseidonPackage] -> [[PoseidonPackage]])
-> [PoseidonPackage] -> [[PoseidonPackage]]
forall a b. (a -> b) -> a -> b
$ [PoseidonPackage]
filteredPackageList
    Bool -> PoseidonIO () -> PoseidonIO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ([[PoseidonPackage]] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [[PoseidonPackage]]
duplicateGroups) (PoseidonIO () -> PoseidonIO ()) -> PoseidonIO () -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ do
        FilePath -> PoseidonIO ()
logError FilePath
"There are duplicated packages in this package collection:"
        [[PoseidonPackage]]
-> ([PoseidonPackage] -> ReaderT Env IO Any) -> PoseidonIO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [[PoseidonPackage]]
duplicateGroups (([PoseidonPackage] -> ReaderT Env IO Any) -> PoseidonIO ())
-> ([PoseidonPackage] -> ReaderT Env IO Any) -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ \[PoseidonPackage]
xs -> do
            FilePath -> PoseidonIO ()
logError (FilePath -> PoseidonIO ()) -> FilePath -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Duplicate package " FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ PacNameAndVersion -> FilePath
forall a. Show a => a -> FilePath
show (PoseidonPackage -> PacNameAndVersion
posPacNameAndVersion (PoseidonPackage -> PacNameAndVersion)
-> PoseidonPackage -> PacNameAndVersion
forall a b. (a -> b) -> a -> b
$ [PoseidonPackage] -> PoseidonPackage
forall a. HasCallStack => [a] -> a
head [PoseidonPackage]
xs) FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ FilePath
" found at"
            [PoseidonPackage]
-> (PoseidonPackage -> PoseidonIO ()) -> PoseidonIO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [PoseidonPackage]
xs ((PoseidonPackage -> PoseidonIO ()) -> PoseidonIO ())
-> (PoseidonPackage -> PoseidonIO ()) -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ \PoseidonPackage
x -> do
                FilePath -> PoseidonIO ()
logError (FilePath -> PoseidonIO ()) -> FilePath -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ FilePath
"  " FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ PoseidonPackage -> FilePath
posPacBaseDir PoseidonPackage
x
            PoseidonException -> ReaderT Env IO Any
forall e a. Exception e => e -> ReaderT Env IO a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (PoseidonException -> ReaderT Env IO Any)
-> (FilePath -> PoseidonException)
-> FilePath
-> ReaderT Env IO Any
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> PoseidonException
PoseidonCollectionException (FilePath -> ReaderT Env IO Any) -> FilePath -> ReaderT Env IO Any
forall a b. (a -> b) -> a -> b
$ FilePath
"Detected duplicate packages."
    -- report number of valid packages
    let finalPackageList :: [PoseidonPackage]
finalPackageList = [PoseidonPackage] -> [PoseidonPackage]
forall a. Ord a => [a] -> [a]
sort [PoseidonPackage]
filteredPackageList
    FilePath -> PoseidonIO ()
logInfo (FilePath -> PoseidonIO ()) -> FilePath -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Packages loaded: " FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ (Int -> FilePath
forall a. Show a => a -> FilePath
show (Int -> FilePath)
-> ([PoseidonPackage] -> Int) -> [PoseidonPackage] -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [PoseidonPackage] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([PoseidonPackage] -> FilePath) -> [PoseidonPackage] -> FilePath
forall a b. (a -> b) -> a -> b
$ [PoseidonPackage]
finalPackageList)
    -- return package list
    ([PoseidonPackage], Bool)
-> ReaderT Env IO ([PoseidonPackage], Bool)
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ([PoseidonPackage]
finalPackageList, Bool
skipIndicator)
  where
    checkIfBaseDirExists :: FilePath -> PoseidonIO (Maybe FilePath)
    checkIfBaseDirExists :: FilePath -> ReaderT Env IO (Maybe FilePath)
checkIfBaseDirExists FilePath
p = do
        Bool
exists <- 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
$ FilePath -> IO Bool
doesDirectoryExist FilePath
p
        if Bool
exists
        then Maybe FilePath -> ReaderT Env IO (Maybe FilePath)
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (FilePath -> Maybe FilePath
forall a. a -> Maybe a
Just FilePath
p)
        else do
            FilePath -> PoseidonIO ()
logWarning (FilePath -> PoseidonIO ()) -> FilePath -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Base directory (-d) " FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ ShowS
forall a. Show a => a -> FilePath
show FilePath
p FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ FilePath
" does not exist"
            Maybe FilePath -> ReaderT Env IO (Maybe FilePath)
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe FilePath
forall a. Maybe a
Nothing
    filterByPoseidonVersion :: [FilePath] -> PoseidonIO [FilePath]
    filterByPoseidonVersion :: [FilePath] -> ReaderT Env IO [FilePath]
filterByPoseidonVersion [FilePath]
posFiles = do
        [Either PoseidonException FilePath]
eitherPaths <- IO [Either PoseidonException FilePath]
-> ReaderT Env IO [Either PoseidonException FilePath]
forall a. IO a -> ReaderT Env IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO [Either PoseidonException FilePath]
 -> ReaderT Env IO [Either PoseidonException FilePath])
-> IO [Either PoseidonException FilePath]
-> ReaderT Env IO [Either PoseidonException FilePath]
forall a b. (a -> b) -> a -> b
$ (FilePath -> IO (Either PoseidonException FilePath))
-> [FilePath] -> IO [Either PoseidonException FilePath]
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 FilePath -> IO (Either PoseidonException FilePath)
isInVersionRange [FilePath]
posFiles
        (PoseidonException -> PoseidonIO ())
-> [PoseidonException] -> PoseidonIO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (FilePath -> PoseidonIO ()
logWarning (FilePath -> PoseidonIO ())
-> (PoseidonException -> FilePath)
-> PoseidonException
-> PoseidonIO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PoseidonException -> FilePath
renderPoseidonException) ([PoseidonException] -> PoseidonIO ())
-> [PoseidonException] -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ [Either PoseidonException FilePath] -> [PoseidonException]
forall a b. [Either a b] -> [a]
lefts [Either PoseidonException FilePath]
eitherPaths
        [FilePath] -> ReaderT Env IO [FilePath]
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ([FilePath] -> ReaderT Env IO [FilePath])
-> [FilePath] -> ReaderT Env IO [FilePath]
forall a b. (a -> b) -> a -> b
$ [Either PoseidonException FilePath] -> [FilePath]
forall a b. [Either a b] -> [b]
rights [Either PoseidonException FilePath]
eitherPaths
        where
            isInVersionRange :: FilePath -> IO (Either PoseidonException FilePath)
            isInVersionRange :: FilePath -> IO (Either PoseidonException FilePath)
isInVersionRange FilePath
posFile = do
                FilePath
content <- FilePath -> IO FilePath
readFile' FilePath
posFile
                let posLines :: [FilePath]
posLines = FilePath -> [FilePath]
lines FilePath
content
                -- This implementation only works with a true YAML file.
                -- But technically also JSON is YAML. If somebody prepares
                -- a POSEIDON.yml file in JSON format, a wrong version
                -- can not be caught.
                case FilePath -> [FilePath] -> Maybe Int
forall a. Eq a => a -> [a] -> Maybe Int
elemIndex FilePath
"poseidonVersion:" (ShowS -> [FilePath] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map (Int -> ShowS
forall a. Int -> [a] -> [a]
take Int
16) [FilePath]
posLines) of
                    Maybe Int
Nothing -> Either PoseidonException FilePath
-> IO (Either PoseidonException FilePath)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either PoseidonException FilePath
 -> IO (Either PoseidonException FilePath))
-> Either PoseidonException FilePath
-> IO (Either PoseidonException FilePath)
forall a b. (a -> b) -> a -> b
$ PoseidonException -> Either PoseidonException FilePath
forall a b. a -> Either a b
Left (PoseidonException -> Either PoseidonException FilePath)
-> PoseidonException -> Either PoseidonException FilePath
forall a b. (a -> b) -> a -> b
$ FilePath -> PoseidonException
PoseidonPackageMissingVersionException FilePath
posFile
                    Just Int
n -> do
                        let versionLine :: FilePath
versionLine = [FilePath]
posLines [FilePath] -> Int -> FilePath
forall a. HasCallStack => [a] -> Int -> a
!! Int
n
                            versionString :: FilePath
versionString = (Char -> Bool) -> ShowS
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool) -> (Char -> Bool) -> Char -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Bool
isSpace) ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$ Int -> ShowS
forall a. Int -> [a] -> [a]
drop Int
16 FilePath
versionLine
                        if FilePath
versionString FilePath -> [FilePath] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` (PoseidonVersion -> FilePath) -> [PoseidonVersion] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map PoseidonVersion -> FilePath
showPoseidonVersion [PoseidonVersion]
validPoseidonVersions
                        then Either PoseidonException FilePath
-> IO (Either PoseidonException FilePath)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either PoseidonException FilePath
 -> IO (Either PoseidonException FilePath))
-> Either PoseidonException FilePath
-> IO (Either PoseidonException FilePath)
forall a b. (a -> b) -> a -> b
$ FilePath -> Either PoseidonException FilePath
forall a b. b -> Either a b
Right FilePath
posFile
                        else Either PoseidonException FilePath
-> IO (Either PoseidonException FilePath)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either PoseidonException FilePath
 -> IO (Either PoseidonException FilePath))
-> Either PoseidonException FilePath
-> IO (Either PoseidonException FilePath)
forall a b. (a -> b) -> a -> b
$ PoseidonException -> Either PoseidonException FilePath
forall a b. a -> Either a b
Left (PoseidonException -> Either PoseidonException FilePath)
-> PoseidonException -> Either PoseidonException FilePath
forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath -> PoseidonException
PoseidonPackageVersionException FilePath
posFile FilePath
versionString
            readFile' :: FilePath -> IO String
            readFile' :: FilePath -> IO FilePath
readFile' FilePath
filename = FilePath -> IOMode -> (Handle -> IO FilePath) -> IO FilePath
forall r. FilePath -> IOMode -> (Handle -> IO r) -> IO r
withFile FilePath
filename IOMode
ReadMode ((Handle -> IO FilePath) -> IO FilePath)
-> (Handle -> IO FilePath) -> IO FilePath
forall a b. (a -> b) -> a -> b
$ \Handle
handle -> do
                FilePath
theContent <- Handle -> IO FilePath
hGetContents Handle
handle
                (Char -> IO Char) -> FilePath -> IO FilePath
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 -> IO Char
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return FilePath
theContent
    tryDecodePoseidonPackage :: (Integer, FilePath) -> PoseidonIO (Either PoseidonException PoseidonPackage)
    tryDecodePoseidonPackage :: (Integer, FilePath)
-> ReaderT Env IO (Either PoseidonException PoseidonPackage)
tryDecodePoseidonPackage (Integer
numberPackage, FilePath
path) = do
        FilePath -> PoseidonIO ()
logDebug (FilePath -> PoseidonIO ()) -> FilePath -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Package " FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ Integer -> FilePath
forall a. Show a => a -> FilePath
show Integer
numberPackage FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ FilePath
": " FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ FilePath
path
        ReaderT Env IO PoseidonPackage
-> ReaderT Env IO (Either PoseidonException PoseidonPackage)
forall (m :: * -> *) e a.
(MonadCatch m, Exception e) =>
m a -> m (Either e a)
try (ReaderT Env IO PoseidonPackage
 -> ReaderT Env IO (Either PoseidonException PoseidonPackage))
-> (FilePath -> ReaderT Env IO PoseidonPackage)
-> FilePath
-> ReaderT Env IO (Either PoseidonException PoseidonPackage)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PackageReadOptions -> FilePath -> ReaderT Env IO PoseidonPackage
readPoseidonPackage PackageReadOptions
opts (FilePath
 -> ReaderT Env IO (Either PoseidonException PoseidonPackage))
-> FilePath
-> ReaderT Env IO (Either PoseidonException PoseidonPackage)
forall a b. (a -> b) -> a -> b
$ FilePath
path

-- | A function to read in a poseidon package from a YAML file. Note that this function calls the addFullPaths function to
-- make paths absolute.
readPoseidonPackage :: PackageReadOptions
                    -> FilePath -- ^ the file path to the yaml file
                    -> PoseidonIO PoseidonPackage -- ^ the returning package returned in the IO monad.
readPoseidonPackage :: PackageReadOptions -> FilePath -> ReaderT Env IO PoseidonPackage
readPoseidonPackage PackageReadOptions
opts FilePath
ymlPath = do
    let baseDir :: FilePath
baseDir = ShowS
takeDirectory FilePath
ymlPath
    ByteString
bs <- IO ByteString -> ReaderT Env IO ByteString
forall a. IO a -> ReaderT Env IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO ByteString -> ReaderT Env IO ByteString)
-> IO ByteString -> ReaderT Env IO ByteString
forall a b. (a -> b) -> a -> b
$ FilePath -> IO ByteString
B.readFile FilePath
ymlPath

    -- read yml files
    yml :: PoseidonYamlStruct
yml@(PoseidonYamlStruct Version
ver FilePath
tit Maybe FilePath
des [ContributorSpec]
con Maybe Version
pacVer Maybe Day
mod_ GenotypeDataSpec
geno Maybe FilePath
jannoF Maybe FilePath
jannoC Maybe FilePath
seqSourceF Maybe FilePath
seqSourceC Maybe FilePath
bibF Maybe FilePath
bibC Maybe FilePath
readF Maybe FilePath
changeF) <- case ByteString -> Either ParseException PoseidonYamlStruct
forall a. FromJSON a => ByteString -> Either ParseException a
decodeEither' ByteString
bs of
        Left ParseException
err  -> PoseidonException -> ReaderT Env IO PoseidonYamlStruct
forall e a. Exception e => e -> ReaderT Env IO a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (PoseidonException -> ReaderT Env IO PoseidonYamlStruct)
-> PoseidonException -> ReaderT Env IO PoseidonYamlStruct
forall a b. (a -> b) -> a -> b
$ FilePath -> ParseException -> PoseidonException
PoseidonYamlParseException FilePath
ymlPath ParseException
err
        Right PoseidonYamlStruct
pac -> PoseidonYamlStruct -> ReaderT Env IO PoseidonYamlStruct
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return PoseidonYamlStruct
pac
    PoseidonYamlStruct -> PoseidonIO ()
checkYML PoseidonYamlStruct
yml

    -- file existence and checksum test
    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
$ FilePath -> Bool -> Bool -> PoseidonYamlStruct -> IO ()
checkFiles FilePath
baseDir (PackageReadOptions -> Bool
_readOptIgnoreChecksums PackageReadOptions
opts) (PackageReadOptions -> Bool
_readOptIgnoreGeno PackageReadOptions
opts) PoseidonYamlStruct
yml

    -- read janno (or fill with empty dummy object)
    [EigenstratIndEntry]
indEntries <- FilePath -> GenotypeDataSpec -> PoseidonIO [EigenstratIndEntry]
loadIndividuals FilePath
baseDir GenotypeDataSpec
geno
    JannoRows
janno <- case FilePath -> PoseidonYamlStruct -> Maybe FilePath
poseidonJannoFilePath FilePath
baseDir PoseidonYamlStruct
yml of
        Maybe FilePath
Nothing -> do
            JannoRows -> ReaderT Env IO JannoRows
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (JannoRows -> ReaderT Env IO JannoRows)
-> JannoRows -> ReaderT Env IO JannoRows
forall a b. (a -> b) -> a -> b
$ [EigenstratIndEntry] -> JannoRows
createMinimalJanno [EigenstratIndEntry]
indEntries
        Just FilePath
p -> do
            JannoRows
loadedJanno <- FilePath -> ReaderT Env IO JannoRows
readJannoFile FilePath
p
            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
$ FilePath -> JannoRows -> [EigenstratIndEntry] -> IO ()
checkJannoIndConsistency FilePath
tit JannoRows
loadedJanno [EigenstratIndEntry]
indEntries
            JannoRows -> ReaderT Env IO JannoRows
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return JannoRows
loadedJanno

    -- read seqSource
    SeqSourceRows
seqSource <- case FilePath -> PoseidonYamlStruct -> Maybe FilePath
poseidonSeqSourceFilePath FilePath
baseDir PoseidonYamlStruct
yml of
        Maybe FilePath
Nothing -> SeqSourceRows -> ReaderT Env IO SeqSourceRows
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return SeqSourceRows
forall a. Monoid a => a
mempty
        Just FilePath
p  -> FilePath -> ReaderT Env IO SeqSourceRows
readSeqSourceFile FilePath
p
    FilePath -> SeqSourceRows -> JannoRows -> PoseidonIO ()
checkSeqSourceJannoConsistency FilePath
tit SeqSourceRows
seqSource JannoRows
janno

    -- read bib (or fill with empty list)
    BibTeX
bib <- case FilePath -> PoseidonYamlStruct -> Maybe FilePath
poseidonBibFilePath FilePath
baseDir PoseidonYamlStruct
yml of
        Maybe FilePath
Nothing -> BibTeX -> ReaderT Env IO BibTeX
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ([] :: BibTeX)
        Just FilePath
p  -> IO BibTeX -> ReaderT Env IO BibTeX
forall a. IO a -> ReaderT Env IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO BibTeX -> ReaderT Env IO BibTeX)
-> IO BibTeX -> ReaderT Env IO BibTeX
forall a b. (a -> b) -> a -> b
$ FilePath -> IO BibTeX
readBibTeXFile FilePath
p
    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
$ FilePath -> JannoRows -> BibTeX -> IO ()
checkJannoBibConsistency FilePath
tit JannoRows
janno BibTeX
bib

    Bool -> PoseidonIO () -> PoseidonIO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (PackageReadOptions -> Bool
_readOptFullGeno PackageReadOptions
opts) (PoseidonIO () -> PoseidonIO ()) -> PoseidonIO () -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ do
        FilePath -> PoseidonIO ()
logInfo (FilePath -> PoseidonIO ()) -> FilePath -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Trying to parse genotype data for package: " FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ FilePath
tit

    -- create PoseidonPackage
    let pac :: PoseidonPackage
pac = FilePath
-> Version
-> PacNameAndVersion
-> Maybe FilePath
-> [ContributorSpec]
-> Maybe Day
-> GenotypeDataSpec
-> Maybe FilePath
-> JannoRows
-> Maybe FilePath
-> Maybe FilePath
-> SeqSourceRows
-> Maybe FilePath
-> Maybe FilePath
-> BibTeX
-> Maybe FilePath
-> Maybe FilePath
-> Maybe FilePath
-> PoseidonPackage
PoseidonPackage FilePath
baseDir Version
ver (FilePath -> Maybe Version -> PacNameAndVersion
PacNameAndVersion FilePath
tit Maybe Version
pacVer) Maybe FilePath
des [ContributorSpec]
con Maybe Day
mod_ GenotypeDataSpec
geno Maybe FilePath
jannoF JannoRows
janno Maybe FilePath
jannoC Maybe FilePath
seqSourceF SeqSourceRows
seqSource Maybe FilePath
seqSourceC Maybe FilePath
bibF BibTeX
bib Maybe FilePath
bibC Maybe FilePath
readF Maybe FilePath
changeF

    -- validate genotype data
    Bool -> PoseidonIO () -> PoseidonIO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not (PackageReadOptions -> Bool
_readOptIgnoreGeno PackageReadOptions
opts) Bool -> Bool -> Bool
&& PackageReadOptions -> Bool
_readOptGenoCheck PackageReadOptions
opts) (PoseidonIO () -> PoseidonIO ()) -> PoseidonIO () -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$
        PoseidonPackage -> Bool -> PoseidonIO ()
validateGeno PoseidonPackage
pac (PackageReadOptions -> Bool
_readOptFullGeno PackageReadOptions
opts)

    -- return complete, valid package
    PoseidonPackage -> ReaderT Env IO PoseidonPackage
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return PoseidonPackage
pac

checkYML :: PoseidonYamlStruct -> PoseidonIO ()
checkYML :: PoseidonYamlStruct -> PoseidonIO ()
checkYML PoseidonYamlStruct
yml = do
    let contributors :: [ContributorSpec]
contributors = PoseidonYamlStruct -> [ContributorSpec]
_posYamlContributor PoseidonYamlStruct
yml
    Bool -> PoseidonIO () -> PoseidonIO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when ([ContributorSpec] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [ContributorSpec]
contributors) (PoseidonIO () -> PoseidonIO ()) -> PoseidonIO () -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ do
        FilePath -> PoseidonIO ()
logWarning (FilePath -> PoseidonIO ()) -> FilePath -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Contributor missing in POSEIDON.yml file of package " FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ PoseidonYamlStruct -> FilePath
forall a. HasNameAndVersion a => a -> FilePath
renderNameWithVersion PoseidonYamlStruct
yml

validateGeno :: PoseidonPackage -> Bool -> PoseidonIO ()
validateGeno :: PoseidonPackage -> Bool -> PoseidonIO ()
validateGeno PoseidonPackage
pac Bool
checkFullGeno = do
    LogA
logA <- PoseidonIO LogA
envLogAction
    PlinkPopNameMode
plinkMode <- PoseidonIO PlinkPopNameMode
envInputPlinkMode
    ErrorLength
errLength <- PoseidonIO ErrorLength
envErrorLength
    --let jannoRows = getJannoRowsFromPac pac
    --let ploidyList = map jGenotypePloidy jannoRows
    --let indivNames = map jPoseidonID jannoRows
    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
            -- we're using getJointGenotypeData here on a single package to check for SNP consistency
            -- since that check is only implemented in the jointLoading function, not in the per-package loading
            ([EigenstratIndEntry]
_, Producer (EigenstratSnpEntry, GenoLine) (SafeT IO) ()
eigenstratProd) <- LogA
-> Bool
-> PlinkPopNameMode
-> [PoseidonPackage]
-> Maybe FilePath
-> SafeT
     IO
     ([EigenstratIndEntry],
      Producer (EigenstratSnpEntry, GenoLine) (SafeT IO) ())
forall (m :: * -> *).
MonadSafe m =>
LogA
-> Bool
-> PlinkPopNameMode
-> [PoseidonPackage]
-> Maybe FilePath
-> m ([EigenstratIndEntry],
      Producer (EigenstratSnpEntry, GenoLine) m ())
getJointGenotypeData LogA
logA Bool
False PlinkPopNameMode
plinkMode [PoseidonPackage
pac] Maybe FilePath
forall a. Maybe a
Nothing
            -- check all or only the first 100 SNPs
            if Bool
checkFullGeno
            then do
                UTCTime
currentTime <- IO UTCTime -> SafeT IO UTCTime
forall a. IO a -> SafeT IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO UTCTime
getCurrentTime
                --runEffect $ eigenstratProd >-> checkPloidy logA ploidyList indivNames >-> printSNPCopyProgress logA currentTime >-> P.drain
                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) ()
-> Proxy () (EigenstratSnpEntry, GenoLine) () X (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
>-> Proxy () (EigenstratSnpEntry, GenoLine) () X (SafeT IO) ()
Consumer' (EigenstratSnpEntry, GenoLine) (SafeT IO) ()
forall (m :: * -> *) a r. Functor m => Consumer' a m r
P.drain
            else
                --runEffect $ eigenstratProd >-> P.take 100 >-> checkPloidy logA ploidyList indivNames >-> P.drain
                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
>-> Int
-> Proxy
     ()
     (EigenstratSnpEntry, GenoLine)
     ()
     (EigenstratSnpEntry, GenoLine)
     (SafeT IO)
     ()
forall (m :: * -> *) a. Functor m => Int -> Pipe a a m ()
P.take Int
100 Producer (EigenstratSnpEntry, GenoLine) (SafeT IO) ()
-> Proxy () (EigenstratSnpEntry, GenoLine) () X (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
>-> Proxy () (EigenstratSnpEntry, GenoLine) () X (SafeT IO) ()
Consumer' (EigenstratSnpEntry, GenoLine) (SafeT IO) ()
forall (m :: * -> *) a r. Functor m => Consumer' a m r
P.drain
        ) (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)
  -- where
  --   checkPloidy logA ploidyList indivNames = for cat $ \(_, genoLine) -> do
  --       let illegals =
  --               map (\(_, ind, _) -> renderNameWithVersion pac ++ ": " ++ ind) .
  --               filter (\(ploidy, _, geno) -> ploidy == Just Haploid && geno == Het) .
  --               zip3 ploidyList indivNames . V.toList $ genoLine
  --       unless (null illegals) $ do
  --           logWithEnv logA . logDebug $ "The following samples have heterozygote genotypes despite being annotated as \"haploid\" in the Janno file:"
  --           mapM_ (logWithEnv logA . logDebug) illegals
  --           liftIO . throwIO $ PoseidonGenotypeException "Illegal heterozygote genotypes for individuals marked as 'haploid' in the Janno file. Choose --logMode VerboseLog to output more"


-- throws exception if any file is missing or checksum is incorrect
checkFiles :: FilePath -> Bool -> Bool -> PoseidonYamlStruct -> IO ()
checkFiles :: FilePath -> Bool -> Bool -> PoseidonYamlStruct -> IO ()
checkFiles FilePath
baseDir Bool
ignoreChecksums Bool
ignoreGenotypeFilesMissing PoseidonYamlStruct
yml = do
    -- Check README File
    case FilePath -> PoseidonYamlStruct -> Maybe FilePath
poseidonReadmeFilePath FilePath
baseDir PoseidonYamlStruct
yml of
        Maybe FilePath
Nothing -> () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
        Just FilePath
fn -> FilePath -> Maybe FilePath -> IO ()
checkFile FilePath
fn Maybe FilePath
forall a. Maybe a
Nothing
    -- Check CHANGELOG File
    case FilePath -> PoseidonYamlStruct -> Maybe FilePath
poseidonChangelogFilePath FilePath
baseDir PoseidonYamlStruct
yml of
        Maybe FilePath
Nothing -> () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
        Just FilePath
fn -> FilePath -> Maybe FilePath -> IO ()
checkFile FilePath
fn Maybe FilePath
forall a. Maybe a
Nothing
    -- Check Bib File
    case FilePath -> PoseidonYamlStruct -> Maybe FilePath
poseidonBibFilePath FilePath
baseDir PoseidonYamlStruct
yml of
        Maybe FilePath
Nothing -> () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
        Just FilePath
fn -> if Bool
ignoreChecksums
                   then FilePath -> Maybe FilePath -> IO ()
checkFile FilePath
fn Maybe FilePath
forall a. Maybe a
Nothing
                   else FilePath -> Maybe FilePath -> IO ()
checkFile FilePath
fn (Maybe FilePath -> IO ()) -> Maybe FilePath -> IO ()
forall a b. (a -> b) -> a -> b
$ PoseidonYamlStruct -> Maybe FilePath
_posYamlBibFileChkSum PoseidonYamlStruct
yml
    -- Check Janno File
    case FilePath -> PoseidonYamlStruct -> Maybe FilePath
poseidonJannoFilePath FilePath
baseDir PoseidonYamlStruct
yml of
        Maybe FilePath
Nothing -> () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
        Just FilePath
fn -> if Bool
ignoreChecksums
                   then FilePath -> Maybe FilePath -> IO ()
checkFile FilePath
fn Maybe FilePath
forall a. Maybe a
Nothing
                   else FilePath -> Maybe FilePath -> IO ()
checkFile FilePath
fn (Maybe FilePath -> IO ()) -> Maybe FilePath -> IO ()
forall a b. (a -> b) -> a -> b
$ PoseidonYamlStruct -> Maybe FilePath
_posYamlJannoFileChkSum PoseidonYamlStruct
yml
    -- Check SeqSource File
    case FilePath -> PoseidonYamlStruct -> Maybe FilePath
poseidonSeqSourceFilePath FilePath
baseDir PoseidonYamlStruct
yml of
        Maybe FilePath
Nothing -> () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
        Just FilePath
fn -> if Bool
ignoreChecksums
                   then FilePath -> Maybe FilePath -> IO ()
checkFile FilePath
fn Maybe FilePath
forall a. Maybe a
Nothing
                   else FilePath -> Maybe FilePath -> IO ()
checkFile FilePath
fn (Maybe FilePath -> IO ()) -> Maybe FilePath -> IO ()
forall a b. (a -> b) -> a -> b
$ PoseidonYamlStruct -> Maybe FilePath
_posYamlSeqSourceFileChkSum PoseidonYamlStruct
yml
    -- Check Genotype files
    Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
ignoreGenotypeFilesMissing (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
        let gd :: GenotypeDataSpec
gd = PoseidonYamlStruct -> GenotypeDataSpec
_posYamlGenotypeData PoseidonYamlStruct
yml
            d :: FilePath
d = FilePath
baseDir
        if Bool
ignoreChecksums
        then do
            FilePath -> Maybe FilePath -> IO ()
checkFile (FilePath
d FilePath -> ShowS
</> GenotypeDataSpec -> FilePath
genoFile GenotypeDataSpec
gd) Maybe FilePath
forall a. Maybe a
Nothing
            FilePath -> Maybe FilePath -> IO ()
checkFile (FilePath
d FilePath -> ShowS
</> GenotypeDataSpec -> FilePath
snpFile GenotypeDataSpec
gd) Maybe FilePath
forall a. Maybe a
Nothing
            FilePath -> Maybe FilePath -> IO ()
checkFile (FilePath
d FilePath -> ShowS
</> GenotypeDataSpec -> FilePath
indFile GenotypeDataSpec
gd) Maybe FilePath
forall a. Maybe a
Nothing
        else do
            FilePath -> Maybe FilePath -> IO ()
checkFile (FilePath
d FilePath -> ShowS
</> GenotypeDataSpec -> FilePath
genoFile GenotypeDataSpec
gd) (Maybe FilePath -> IO ()) -> Maybe FilePath -> IO ()
forall a b. (a -> b) -> a -> b
$ GenotypeDataSpec -> Maybe FilePath
genoFileChkSum GenotypeDataSpec
gd
            FilePath -> Maybe FilePath -> IO ()
checkFile (FilePath
d FilePath -> ShowS
</> GenotypeDataSpec -> FilePath
snpFile GenotypeDataSpec
gd) (Maybe FilePath -> IO ()) -> Maybe FilePath -> IO ()
forall a b. (a -> b) -> a -> b
$ GenotypeDataSpec -> Maybe FilePath
snpFileChkSum GenotypeDataSpec
gd
            FilePath -> Maybe FilePath -> IO ()
checkFile (FilePath
d FilePath -> ShowS
</> GenotypeDataSpec -> FilePath
indFile GenotypeDataSpec
gd) (Maybe FilePath -> IO ()) -> Maybe FilePath -> IO ()
forall a b. (a -> b) -> a -> b
$ GenotypeDataSpec -> Maybe FilePath
indFileChkSum GenotypeDataSpec
gd

checkJannoIndConsistency :: String -> JannoRows -> [EigenstratIndEntry] -> IO ()
checkJannoIndConsistency :: FilePath -> JannoRows -> [EigenstratIndEntry] -> IO ()
checkJannoIndConsistency FilePath
pacName (JannoRows [JannoRow]
rows) [EigenstratIndEntry]
indEntries = do
    let genoIDs :: [FilePath]
genoIDs         = [ FilePath
x | EigenstratIndEntry  FilePath
x Sex
_ FilePath
_ <- [EigenstratIndEntry]
indEntries]
        genoSexs :: [Sex]
genoSexs        = [ Sex
x | EigenstratIndEntry  FilePath
_ Sex
x FilePath
_ <- [EigenstratIndEntry]
indEntries]
        genoGroups :: [FilePath]
genoGroups      = [ FilePath
x | EigenstratIndEntry  FilePath
_ Sex
_ FilePath
x <- [EigenstratIndEntry]
indEntries]
    let jannoIDs :: [FilePath]
jannoIDs        = (JannoRow -> FilePath) -> [JannoRow] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map JannoRow -> FilePath
jPoseidonID [JannoRow]
rows
        jannoSexs :: [Sex]
jannoSexs       = (JannoRow -> Sex) -> [JannoRow] -> [Sex]
forall a b. (a -> b) -> [a] -> [b]
map (JannoSex -> Sex
sfSex (JannoSex -> Sex) -> (JannoRow -> JannoSex) -> JannoRow -> Sex
forall b c a. (b -> c) -> (a -> b) -> a -> c
. JannoRow -> JannoSex
jGeneticSex) [JannoRow]
rows
        jannoGroups :: [FilePath]
jannoGroups     = (JannoRow -> FilePath) -> [JannoRow] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map ([FilePath] -> FilePath
forall a. HasCallStack => [a] -> a
head ([FilePath] -> FilePath)
-> (JannoRow -> [FilePath]) -> JannoRow -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. JannoList FilePath -> [FilePath]
forall a. JannoList a -> [a]
getJannoList (JannoList FilePath -> [FilePath])
-> (JannoRow -> JannoList FilePath) -> JannoRow -> [FilePath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. JannoRow -> JannoList FilePath
jGroupName) [JannoRow]
rows
    let idMis :: Bool
idMis           = [FilePath]
genoIDs [FilePath] -> [FilePath] -> Bool
forall a. Eq a => a -> a -> Bool
/= [FilePath]
jannoIDs
        sexMis :: Bool
sexMis          = [Sex]
genoSexs [Sex] -> [Sex] -> Bool
forall a. Eq a => a -> a -> Bool
/= [Sex]
jannoSexs
        groupMis :: Bool
groupMis        = [FilePath]
genoGroups [FilePath] -> [FilePath] -> Bool
forall a. Eq a => a -> a -> Bool
/= [FilePath]
jannoGroups
    Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
idMis (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ PoseidonException -> IO ()
forall e a. Exception e => e -> IO a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (PoseidonException -> IO ()) -> PoseidonException -> IO ()
forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath -> PoseidonException
PoseidonCrossFileConsistencyException FilePath
pacName (FilePath -> PoseidonException) -> FilePath -> PoseidonException
forall a b. (a -> b) -> a -> b
$
        FilePath
"Individual ID mismatch between genotype data (left) and .janno files (right): " FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++
        [FilePath] -> [FilePath] -> FilePath
renderMismatch [FilePath]
genoIDs [FilePath]
jannoIDs
    Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
sexMis (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ PoseidonException -> IO ()
forall e a. Exception e => e -> IO a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (PoseidonException -> IO ()) -> PoseidonException -> IO ()
forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath -> PoseidonException
PoseidonCrossFileConsistencyException FilePath
pacName (FilePath -> PoseidonException) -> FilePath -> PoseidonException
forall a b. (a -> b) -> a -> b
$
        FilePath
"Individual Sex mismatch between genotype data (left) and .janno files (right): " FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++
        [FilePath] -> [FilePath] -> FilePath
renderMismatch ((Sex -> FilePath) -> [Sex] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map Sex -> FilePath
forall a. Show a => a -> FilePath
show [Sex]
genoSexs) ((Sex -> FilePath) -> [Sex] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map Sex -> FilePath
forall a. Show a => a -> FilePath
show [Sex]
jannoSexs)
    Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
groupMis (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ PoseidonException -> IO ()
forall e a. Exception e => e -> IO a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (PoseidonException -> IO ()) -> PoseidonException -> IO ()
forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath -> PoseidonException
PoseidonCrossFileConsistencyException FilePath
pacName (FilePath -> PoseidonException) -> FilePath -> PoseidonException
forall a b. (a -> b) -> a -> b
$
        FilePath
"Individual GroupID mismatch between genotype data (left) and .janno files (right). Note \
        \that this could be due to a wrong Plink file population-name encoding \
        \(see the --inPlinkPopName option). " FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++
        [FilePath] -> [FilePath] -> FilePath
renderMismatch [FilePath]
genoGroups [FilePath]
jannoGroups

renderMismatch :: [String] -> [String] -> String
renderMismatch :: [FilePath] -> [FilePath] -> FilePath
renderMismatch [FilePath]
a [FilePath]
b =
    let misMatchList :: [FilePath]
misMatchList = ((FilePath, FilePath) -> FilePath)
-> [(FilePath, FilePath)] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map (\ (FilePath
x, FilePath
y) -> FilePath
"(" FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ FilePath
x FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ FilePath
" = " FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ FilePath
y FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ FilePath
")")
                       (((FilePath, FilePath) -> Bool)
-> [(FilePath, FilePath)] -> [(FilePath, FilePath)]
forall a. (a -> Bool) -> [a] -> [a]
filter ((FilePath -> FilePath -> Bool) -> (FilePath, FilePath) -> Bool
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
(/=)) ([(FilePath, FilePath)] -> [(FilePath, FilePath)])
-> [(FilePath, FilePath)] -> [(FilePath, FilePath)]
forall a b. (a -> b) -> a -> b
$ FilePath
-> FilePath -> [FilePath] -> [FilePath] -> [(FilePath, FilePath)]
forall a b. a -> b -> [a] -> [b] -> [(a, b)]
zipWithPadding FilePath
"?" FilePath
"?" [FilePath]
a [FilePath]
b)
    in if [FilePath] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [FilePath]
misMatchList Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
5
       then FilePath -> [FilePath] -> FilePath
forall a. [a] -> [[a]] -> [a]
intercalate FilePath
", " (Int -> [FilePath] -> [FilePath]
forall a. Int -> [a] -> [a]
take Int
5 [FilePath]
misMatchList) FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ FilePath
", ..."
       else FilePath -> [FilePath] -> FilePath
forall a. [a] -> [[a]] -> [a]
intercalate FilePath
", " [FilePath]
misMatchList

zipWithPadding :: a -> b -> [a] -> [b] -> [(a,b)]
zipWithPadding :: forall a b. a -> b -> [a] -> [b] -> [(a, b)]
zipWithPadding a
a b
b (a
x:[a]
xs) (b
y:[b]
ys) = (a
x,b
y) (a, b) -> [(a, b)] -> [(a, b)]
forall a. a -> [a] -> [a]
: a -> b -> [a] -> [b] -> [(a, b)]
forall a b. a -> b -> [a] -> [b] -> [(a, b)]
zipWithPadding a
a b
b [a]
xs [b]
ys
zipWithPadding a
a b
_ []     [b]
ys     = [a] -> [b] -> [(a, b)]
forall a b. [a] -> [b] -> [(a, b)]
zip (a -> [a]
forall a. a -> [a]
repeat a
a) [b]
ys
zipWithPadding a
_ b
b [a]
xs     []     = [a] -> [b] -> [(a, b)]
forall a b. [a] -> [b] -> [(a, b)]
zip [a]
xs (b -> [b]
forall a. a -> [a]
repeat b
b)

checkSeqSourceJannoConsistency :: String -> SeqSourceRows -> JannoRows -> PoseidonIO ()
checkSeqSourceJannoConsistency :: FilePath -> SeqSourceRows -> JannoRows -> PoseidonIO ()
checkSeqSourceJannoConsistency FilePath
pacName (SeqSourceRows [SeqSourceRow]
sRows) (JannoRows [JannoRow]
jRows) = do
    PoseidonIO ()
checkPoseidonIDOverlap
    PoseidonIO ()
checkUDGandLibraryBuiltOverlap
    where
        js :: [(FilePath, Maybe JannoUDG, Maybe JannoLibraryBuilt)]
js = (JannoRow -> (FilePath, Maybe JannoUDG, Maybe JannoLibraryBuilt))
-> [JannoRow]
-> [(FilePath, Maybe JannoUDG, Maybe JannoLibraryBuilt)]
forall a b. (a -> b) -> [a] -> [b]
map (\JannoRow
r -> (JannoRow -> FilePath
jPoseidonID JannoRow
r, JannoRow -> Maybe JannoUDG
jUDG JannoRow
r, JannoRow -> Maybe JannoLibraryBuilt
jLibraryBuilt JannoRow
r)) [JannoRow]
jRows
        ss :: [([FilePath], Maybe SSFUDG, Maybe SSFLibraryBuilt)]
ss = (SeqSourceRow -> ([FilePath], Maybe SSFUDG, Maybe SSFLibraryBuilt))
-> [SeqSourceRow]
-> [([FilePath], Maybe SSFUDG, Maybe SSFLibraryBuilt)]
forall a b. (a -> b) -> [a] -> [b]
map (\SeqSourceRow
r -> (Maybe (JannoList FilePath) -> [FilePath]
forall a. Maybe (JannoList a) -> [a]
getMaybeJannoList (Maybe (JannoList FilePath) -> [FilePath])
-> Maybe (JannoList FilePath) -> [FilePath]
forall a b. (a -> b) -> a -> b
$ SeqSourceRow -> Maybe (JannoList FilePath)
sPoseidonID SeqSourceRow
r, SeqSourceRow -> Maybe SSFUDG
sUDG SeqSourceRow
r, SeqSourceRow -> Maybe SSFLibraryBuilt
sLibraryBuilt SeqSourceRow
r)) [SeqSourceRow]
sRows
        checkPoseidonIDOverlap :: PoseidonIO ()
        checkPoseidonIDOverlap :: PoseidonIO ()
checkPoseidonIDOverlap = do
            let flatSeqSourceIDs :: [FilePath]
flatSeqSourceIDs = [FilePath] -> [FilePath]
forall a. Eq a => [a] -> [a]
nub ([FilePath] -> [FilePath]) -> [FilePath] -> [FilePath]
forall a b. (a -> b) -> a -> b
$ [[FilePath]] -> [FilePath]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[FilePath]] -> [FilePath]) -> [[FilePath]] -> [FilePath]
forall a b. (a -> b) -> a -> b
$ [[FilePath]
a | ([FilePath]
a,Maybe SSFUDG
_,Maybe SSFLibraryBuilt
_) <- [([FilePath], Maybe SSFUDG, Maybe SSFLibraryBuilt)]
ss]
                misMatch :: [FilePath]
misMatch = [FilePath]
flatSeqSourceIDs [FilePath] -> [FilePath] -> [FilePath]
forall a. Eq a => [a] -> [a] -> [a]
\\ [FilePath
a | (FilePath
a,Maybe JannoUDG
_,Maybe JannoLibraryBuilt
_) <- [(FilePath, Maybe JannoUDG, Maybe JannoLibraryBuilt)]
js]
            Bool -> PoseidonIO () -> PoseidonIO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ([FilePath] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [FilePath]
misMatch) (PoseidonIO () -> PoseidonIO ()) -> PoseidonIO () -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ do
                FilePath -> PoseidonIO ()
logWarning (FilePath -> PoseidonIO ()) -> FilePath -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ FilePath
"The .ssf file in the package " FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ FilePath
pacName FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++
                    FilePath
" features Poseidon_IDs that are not in the package: " FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ FilePath -> [FilePath] -> FilePath
forall a. [a] -> [[a]] -> [a]
intercalate FilePath
", " [FilePath]
misMatch
        checkUDGandLibraryBuiltOverlap :: PoseidonIO ()
        checkUDGandLibraryBuiltOverlap :: PoseidonIO ()
checkUDGandLibraryBuiltOverlap = do
            ((FilePath, Maybe JannoUDG, Maybe JannoLibraryBuilt)
 -> PoseidonIO ())
-> [(FilePath, Maybe JannoUDG, Maybe JannoLibraryBuilt)]
-> PoseidonIO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (FilePath, Maybe JannoUDG, Maybe JannoLibraryBuilt)
-> PoseidonIO ()
checkOneIndividual [(FilePath, Maybe JannoUDG, Maybe JannoLibraryBuilt)]
js
            where
                checkOneIndividual :: (String, Maybe JannoUDG, Maybe JannoLibraryBuilt) -> PoseidonIO ()
                checkOneIndividual :: (FilePath, Maybe JannoUDG, Maybe JannoLibraryBuilt)
-> PoseidonIO ()
checkOneIndividual (FilePath
jannoPoseidonID, Maybe JannoUDG
jannoUDG, Maybe JannoLibraryBuilt
jannoLibraryBuilt) = do
                    let relevantSeqSourceRows :: [([FilePath], Maybe SSFUDG, Maybe SSFLibraryBuilt)]
relevantSeqSourceRows = (([FilePath], Maybe SSFUDG, Maybe SSFLibraryBuilt) -> Bool)
-> [([FilePath], Maybe SSFUDG, Maybe SSFLibraryBuilt)]
-> [([FilePath], Maybe SSFUDG, Maybe SSFLibraryBuilt)]
forall a. (a -> Bool) -> [a] -> [a]
filter (\([FilePath]
seqSourcePoseidonID,Maybe SSFUDG
_,Maybe SSFLibraryBuilt
_) -> FilePath
jannoPoseidonID FilePath -> [FilePath] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [FilePath]
seqSourcePoseidonID) [([FilePath], Maybe SSFUDG, Maybe SSFLibraryBuilt)]
ss
                        allSeqSourceUDGs :: [SSFUDG]
allSeqSourceUDGs = [Maybe SSFUDG] -> [SSFUDG]
forall a. [Maybe a] -> [a]
catMaybes ([Maybe SSFUDG] -> [SSFUDG]) -> [Maybe SSFUDG] -> [SSFUDG]
forall a b. (a -> b) -> a -> b
$ [Maybe SSFUDG
b | ([FilePath]
_,Maybe SSFUDG
b,Maybe SSFLibraryBuilt
_) <- [([FilePath], Maybe SSFUDG, Maybe SSFLibraryBuilt)]
relevantSeqSourceRows]
                        allSeqSourceLibraryBuilts :: [SSFLibraryBuilt]
allSeqSourceLibraryBuilts = [Maybe SSFLibraryBuilt] -> [SSFLibraryBuilt]
forall a. [Maybe a] -> [a]
catMaybes ([Maybe SSFLibraryBuilt] -> [SSFLibraryBuilt])
-> [Maybe SSFLibraryBuilt] -> [SSFLibraryBuilt]
forall a b. (a -> b) -> a -> b
$ [Maybe SSFLibraryBuilt
c | ([FilePath]
_,Maybe SSFUDG
_,Maybe SSFLibraryBuilt
c) <- [([FilePath], Maybe SSFUDG, Maybe SSFLibraryBuilt)]
relevantSeqSourceRows]
                    case Maybe JannoUDG
jannoUDG of
                        Maybe JannoUDG
Nothing -> () -> PoseidonIO ()
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
                        Just JannoUDG
j -> Bool -> PoseidonIO () -> PoseidonIO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ((SSFUDG -> Bool) -> [SSFUDG] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (JannoUDG -> SSFUDG -> Bool
compareU JannoUDG
j) [SSFUDG]
allSeqSourceUDGs) (PoseidonIO () -> PoseidonIO ()) -> PoseidonIO () -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$
                            PoseidonException -> PoseidonIO ()
forall e a. Exception e => e -> ReaderT Env IO a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (PoseidonException -> PoseidonIO ())
-> PoseidonException -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath -> PoseidonException
PoseidonCrossFileConsistencyException FilePath
pacName (FilePath -> PoseidonException) -> FilePath -> PoseidonException
forall a b. (a -> b) -> a -> b
$
                            FilePath
"The information on UDG treatment in .janno and .ssf do not match" FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++
                            FilePath
" for the individual: " FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ FilePath
jannoPoseidonID FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ FilePath
" (" FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ JannoUDG -> FilePath
forall a. Show a => a -> FilePath
show JannoUDG
j FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ FilePath
" <> " FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ [SSFUDG] -> FilePath
forall a. Show a => a -> FilePath
show [SSFUDG]
allSeqSourceUDGs FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ FilePath
")"
                    case Maybe JannoLibraryBuilt
jannoLibraryBuilt of
                        Maybe JannoLibraryBuilt
Nothing -> () -> PoseidonIO ()
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
                        Just JannoLibraryBuilt
j -> Bool -> PoseidonIO () -> PoseidonIO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ((SSFLibraryBuilt -> Bool) -> [SSFLibraryBuilt] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (JannoLibraryBuilt -> SSFLibraryBuilt -> Bool
compareL JannoLibraryBuilt
j) [SSFLibraryBuilt]
allSeqSourceLibraryBuilts) (PoseidonIO () -> PoseidonIO ()) -> PoseidonIO () -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$
                            PoseidonException -> PoseidonIO ()
forall e a. Exception e => e -> ReaderT Env IO a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (PoseidonException -> PoseidonIO ())
-> PoseidonException -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath -> PoseidonException
PoseidonCrossFileConsistencyException FilePath
pacName (FilePath -> PoseidonException) -> FilePath -> PoseidonException
forall a b. (a -> b) -> a -> b
$
                            FilePath
"The information on library strandedness in .janno and .ssf do not match" FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++
                            FilePath
" for the individual: " FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ FilePath
jannoPoseidonID FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ FilePath
" (" FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ JannoLibraryBuilt -> FilePath
forall a. Show a => a -> FilePath
show JannoLibraryBuilt
j FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ FilePath
" <> " FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ [SSFLibraryBuilt] -> FilePath
forall a. Show a => a -> FilePath
show [SSFLibraryBuilt]
allSeqSourceLibraryBuilts FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ FilePath
")"
                compareU :: JannoUDG -> SSFUDG -> Bool
                compareU :: JannoUDG -> SSFUDG -> Bool
compareU JannoUDG
Mixed SSFUDG
_        = Bool
True
                compareU JannoUDG
Minus SSFUDG
SSFMinus = Bool
True
                compareU JannoUDG
Half  SSFUDG
SSFHalf  = Bool
True
                compareU JannoUDG
Plus  SSFUDG
SSFPlus  = Bool
True
                compareU JannoUDG
_     SSFUDG
_        = Bool
False
                compareL :: JannoLibraryBuilt -> SSFLibraryBuilt -> Bool
                compareL :: JannoLibraryBuilt -> SSFLibraryBuilt -> Bool
compareL JannoLibraryBuilt
MixedSSDS SSFLibraryBuilt
_     = Bool
True
                compareL JannoLibraryBuilt
DS        SSFLibraryBuilt
SSFDS = Bool
True
                compareL JannoLibraryBuilt
SS        SSFLibraryBuilt
SSFSS = Bool
True
                compareL JannoLibraryBuilt
_         SSFLibraryBuilt
_     = Bool
False

checkJannoBibConsistency :: String -> JannoRows -> BibTeX -> IO ()
checkJannoBibConsistency :: FilePath -> JannoRows -> BibTeX -> IO ()
checkJannoBibConsistency FilePath
pacName (JannoRows [JannoRow]
rows) BibTeX
bibtex = do
    -- Cross-file consistency
    let literatureInJanno :: [FilePath]
literatureInJanno = [FilePath] -> [FilePath]
forall a. Eq a => [a] -> [a]
nub ([FilePath] -> [FilePath])
-> ([JannoRow] -> [FilePath]) -> [JannoRow] -> [FilePath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (JannoList FilePath -> [FilePath])
-> [JannoList FilePath] -> [FilePath]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap JannoList FilePath -> [FilePath]
forall a. JannoList a -> [a]
getJannoList ([JannoList FilePath] -> [FilePath])
-> ([JannoRow] -> [JannoList FilePath]) -> [JannoRow] -> [FilePath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (JannoRow -> Maybe (JannoList FilePath))
-> [JannoRow] -> [JannoList FilePath]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe JannoRow -> Maybe (JannoList FilePath)
jPublication ([JannoRow] -> [FilePath]) -> [JannoRow] -> [FilePath]
forall a b. (a -> b) -> a -> b
$ [JannoRow]
rows
        literatureInBib :: [FilePath]
literatureInBib = [FilePath] -> [FilePath]
forall a. Eq a => [a] -> [a]
nub ([FilePath] -> [FilePath]) -> [FilePath] -> [FilePath]
forall a b. (a -> b) -> a -> b
$ (BibEntry -> FilePath) -> BibTeX -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map BibEntry -> FilePath
bibEntryId BibTeX
bibtex
        literatureNotInBibButInJanno :: [FilePath]
literatureNotInBibButInJanno = [FilePath]
literatureInJanno [FilePath] -> [FilePath] -> [FilePath]
forall a. Eq a => [a] -> [a] -> [a]
\\ [FilePath]
literatureInBib
    Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ([FilePath] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [FilePath]
literatureNotInBibButInJanno) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ PoseidonException -> IO ()
forall e a. Exception e => e -> IO a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (PoseidonException -> IO ()) -> PoseidonException -> IO ()
forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath -> PoseidonException
PoseidonCrossFileConsistencyException FilePath
pacName (FilePath -> PoseidonException) -> FilePath -> PoseidonException
forall a b. (a -> b) -> a -> b
$
        FilePath
"The following papers lack BibTeX entries: " FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++
        FilePath -> [FilePath] -> FilePath
forall a. [a] -> [[a]] -> [a]
intercalate FilePath
", " [FilePath]
literatureNotInBibButInJanno

findAllPoseidonYmlFiles :: FilePath -> IO [FilePath]
findAllPoseidonYmlFiles :: FilePath -> IO [FilePath]
findAllPoseidonYmlFiles FilePath
baseDir = do
    [FilePath]
entries <- FilePath -> IO [FilePath]
listDirectory FilePath
baseDir
    let posFiles :: [FilePath]
posFiles = ShowS -> [FilePath] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map (FilePath
baseDir FilePath -> ShowS
</>) ([FilePath] -> [FilePath]) -> [FilePath] -> [FilePath]
forall a b. (a -> b) -> a -> b
$ (FilePath -> Bool) -> [FilePath] -> [FilePath]
forall a. (a -> Bool) -> [a] -> [a]
filter (FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
==FilePath
"POSEIDON.yml") ([FilePath] -> [FilePath]) -> [FilePath] -> [FilePath]
forall a b. (a -> b) -> a -> b
$ ShowS -> [FilePath] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map ShowS
takeFileName [FilePath]
entries
    [FilePath]
subDirs <- (FilePath -> IO Bool) -> [FilePath] -> IO [FilePath]
forall (m :: * -> *) a.
Applicative m =>
(a -> m Bool) -> [a] -> m [a]
filterM FilePath -> IO Bool
doesDirectoryExist ([FilePath] -> IO [FilePath])
-> ([FilePath] -> [FilePath]) -> [FilePath] -> IO [FilePath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShowS -> [FilePath] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map (FilePath
baseDir FilePath -> ShowS
</>) ([FilePath] -> IO [FilePath]) -> [FilePath] -> IO [FilePath]
forall a b. (a -> b) -> a -> b
$ [FilePath]
entries
    [FilePath]
morePosFiles <- ([[FilePath]] -> [FilePath]) -> IO [[FilePath]] -> IO [FilePath]
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [[FilePath]] -> [FilePath]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat (IO [[FilePath]] -> IO [FilePath])
-> ([FilePath] -> IO [[FilePath]]) -> [FilePath] -> IO [FilePath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (FilePath -> IO [FilePath]) -> [FilePath] -> IO [[FilePath]]
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 FilePath -> IO [FilePath]
findAllPoseidonYmlFiles ([FilePath] -> IO [FilePath]) -> [FilePath] -> IO [FilePath]
forall a b. (a -> b) -> a -> b
$ [FilePath]
subDirs
    [FilePath] -> IO [FilePath]
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ([FilePath] -> IO [FilePath]) -> [FilePath] -> IO [FilePath]
forall a b. (a -> b) -> a -> b
$ [FilePath]
posFiles [FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++ [FilePath]
morePosFiles

-- | A function to read genotype data jointly from multiple packages
getJointGenotypeData :: MonadSafe m =>
                        LogA -- ^ how messages should be logged
                     -> Bool -- ^ whether to generate an intersection instead of union of input sites
                     -> PlinkPopNameMode -- ^ how to read population labels from Plink
                     -> [PoseidonPackage] -- ^ A list of poseidon packages.
                     -> Maybe FilePath -- ^ a genotype file to select SNPs from
                     -> m ([EigenstratIndEntry], Producer (EigenstratSnpEntry, GenoLine) m ())
                     -- ^ a pair of the EigenstratIndEntries and a Producer over the Snp position values and the genotype line, joined across all packages.
getJointGenotypeData :: forall (m :: * -> *).
MonadSafe m =>
LogA
-> Bool
-> PlinkPopNameMode
-> [PoseidonPackage]
-> Maybe FilePath
-> m ([EigenstratIndEntry],
      Producer (EigenstratSnpEntry, GenoLine) m ())
getJointGenotypeData LogA
logA Bool
intersect PlinkPopNameMode
popMode [PoseidonPackage]
pacs Maybe FilePath
maybeSnpFile = do
    [([EigenstratIndEntry],
  Producer (EigenstratSnpEntry, GenoLine) m ())]
genotypeTuples <- [m ([EigenstratIndEntry],
    Producer (EigenstratSnpEntry, GenoLine) m ())]
-> m [([EigenstratIndEntry],
       Producer (EigenstratSnpEntry, GenoLine) m ())]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
forall (m :: * -> *) a. Monad m => [m a] -> m [a]
sequence [FilePath
-> GenotypeDataSpec
-> PlinkPopNameMode
-> m ([EigenstratIndEntry],
      Producer (EigenstratSnpEntry, GenoLine) m ())
forall (m :: * -> *).
MonadSafe m =>
FilePath
-> GenotypeDataSpec
-> PlinkPopNameMode
-> m ([EigenstratIndEntry],
      Producer (EigenstratSnpEntry, GenoLine) m ())
loadGenotypeData (PoseidonPackage -> FilePath
posPacBaseDir PoseidonPackage
pac) (PoseidonPackage -> GenotypeDataSpec
posPacGenotypeData PoseidonPackage
pac) PlinkPopNameMode
popMode | PoseidonPackage
pac <- [PoseidonPackage]
pacs]
    let indEntries :: [[EigenstratIndEntry]]
indEntries      = (([EigenstratIndEntry],
  Producer (EigenstratSnpEntry, GenoLine) m ())
 -> [EigenstratIndEntry])
-> [([EigenstratIndEntry],
     Producer (EigenstratSnpEntry, GenoLine) m ())]
-> [[EigenstratIndEntry]]
forall a b. (a -> b) -> [a] -> [b]
map ([EigenstratIndEntry],
 Producer (EigenstratSnpEntry, GenoLine) m ())
-> [EigenstratIndEntry]
forall a b. (a, b) -> a
fst [([EigenstratIndEntry],
  Producer (EigenstratSnpEntry, GenoLine) m ())]
genotypeTuples
        jointIndEntries :: [EigenstratIndEntry]
jointIndEntries = [[EigenstratIndEntry]] -> [EigenstratIndEntry]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[EigenstratIndEntry]]
indEntries
        nrInds :: [Int]
nrInds          = ([EigenstratIndEntry] -> Int) -> [[EigenstratIndEntry]] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map [EigenstratIndEntry] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [[EigenstratIndEntry]]
indEntries
        pacNames :: [FilePath]
pacNames        = (PoseidonPackage -> FilePath) -> [PoseidonPackage] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map PoseidonPackage -> FilePath
forall a. HasNameAndVersion a => a -> FilePath
getPacName [PoseidonPackage]
pacs
        prod :: Proxy X () () (EigenstratSnpEntry, GenoLine) m [()]
prod            = (((EigenstratSnpEntry, GenoLine)
 -> (EigenstratSnpEntry, GenoLine) -> Ordering)
-> [Producer (EigenstratSnpEntry, GenoLine) m ()]
-> Producer [Maybe (EigenstratSnpEntry, GenoLine)] m [()]
forall (m :: * -> *) a r.
Monad m =>
(a -> a -> Ordering)
-> [Producer a m r] -> Producer [Maybe a] m [r]
orderedZipAll (EigenstratSnpEntry, GenoLine)
-> (EigenstratSnpEntry, GenoLine) -> Ordering
compFunc ([Producer (EigenstratSnpEntry, GenoLine) m ()]
 -> Producer [Maybe (EigenstratSnpEntry, GenoLine)] m [()])
-> ([([EigenstratIndEntry],
      Producer (EigenstratSnpEntry, GenoLine) m ())]
    -> [Producer (EigenstratSnpEntry, GenoLine) m ()])
-> [([EigenstratIndEntry],
     Producer (EigenstratSnpEntry, GenoLine) m ())]
-> Producer [Maybe (EigenstratSnpEntry, GenoLine)] m [()]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (([EigenstratIndEntry],
  Producer (EigenstratSnpEntry, GenoLine) m ())
 -> Producer (EigenstratSnpEntry, GenoLine) m ())
-> [([EigenstratIndEntry],
     Producer (EigenstratSnpEntry, GenoLine) m ())]
-> [Producer (EigenstratSnpEntry, GenoLine) m ()]
forall a b. (a -> b) -> [a] -> [b]
map ([EigenstratIndEntry],
 Producer (EigenstratSnpEntry, GenoLine) m ())
-> Producer (EigenstratSnpEntry, GenoLine) m ()
forall a b. (a, b) -> b
snd) [([EigenstratIndEntry],
  Producer (EigenstratSnpEntry, GenoLine) m ())]
genotypeTuples Producer [Maybe (EigenstratSnpEntry, GenoLine)] m [()]
-> Proxy
     ()
     [Maybe (EigenstratSnpEntry, GenoLine)]
     ()
     [Maybe (EigenstratSnpEntry, GenoLine)]
     m
     [()]
-> Producer [Maybe (EigenstratSnpEntry, GenoLine)] m [()]
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
>->
                                ([Maybe (EigenstratSnpEntry, GenoLine)] -> Bool)
-> Proxy
     ()
     [Maybe (EigenstratSnpEntry, GenoLine)]
     ()
     [Maybe (EigenstratSnpEntry, GenoLine)]
     m
     [()]
forall (m :: * -> *) a r. Functor m => (a -> Bool) -> Pipe a a m r
P.filter [Maybe (EigenstratSnpEntry, GenoLine)] -> Bool
filterUnionOrIntersection Producer [Maybe (EigenstratSnpEntry, GenoLine)] m [()]
-> Proxy
     ()
     [Maybe (EigenstratSnpEntry, GenoLine)]
     ()
     (EigenstratSnpEntry, GenoLine)
     m
     [()]
-> Proxy X () () (EigenstratSnpEntry, GenoLine) m [()]
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
-> [Int]
-> [FilePath]
-> Proxy
     ()
     [Maybe (EigenstratSnpEntry, GenoLine)]
     ()
     (EigenstratSnpEntry, GenoLine)
     m
     [()]
forall (m :: * -> *) r.
MonadIO m =>
LogA
-> [Int]
-> [FilePath]
-> Pipe
     [Maybe (EigenstratSnpEntry, GenoLine)]
     (EigenstratSnpEntry, GenoLine)
     m
     r
joinEntryPipe LogA
logA [Int]
nrInds [FilePath]
pacNames
    Proxy X () () (EigenstratSnpEntry, GenoLine) m [()]
jointProducer <- case Maybe FilePath
maybeSnpFile of
        Maybe FilePath
Nothing -> do
            Proxy X () () (EigenstratSnpEntry, GenoLine) m [()]
-> m (Proxy X () () (EigenstratSnpEntry, GenoLine) m [()])
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Proxy X () () (EigenstratSnpEntry, GenoLine) m [()]
prod
        Just FilePath
fn -> do
            let snpProd :: Proxy X () () EigenstratSnpEntry m ()
snpProd = FilePath -> Proxy X () () EigenstratSnpEntry m ()
forall (m :: * -> *).
MonadSafe m =>
FilePath -> Producer EigenstratSnpEntry m ()
loadBimOrSnpFile FilePath
fn Proxy X () () EigenstratSnpEntry m ()
-> Proxy () EigenstratSnpEntry () EigenstratSnpEntry m ()
-> Proxy X () () EigenstratSnpEntry m ()
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
>-> (EigenstratSnpEntry -> EigenstratSnpEntry -> Ordering)
-> Proxy () EigenstratSnpEntry () EigenstratSnpEntry m ()
forall (m :: * -> *) a r.
(MonadIO m, MonadSafe m, Show a) =>
(a -> a -> Ordering) -> Pipe a a m r
orderCheckPipe EigenstratSnpEntry -> EigenstratSnpEntry -> Ordering
compFunc3
            Proxy X () () (EigenstratSnpEntry, GenoLine) m [()]
-> m (Proxy X () () (EigenstratSnpEntry, GenoLine) m [()])
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Proxy X () () (EigenstratSnpEntry, GenoLine) m [()]
 -> m (Proxy X () () (EigenstratSnpEntry, GenoLine) m [()]))
-> Proxy X () () (EigenstratSnpEntry, GenoLine) m [()]
-> m (Proxy X () () (EigenstratSnpEntry, GenoLine) m [()])
forall a b. (a -> b) -> a -> b
$ ((EigenstratSnpEntry -> (EigenstratSnpEntry, GenoLine) -> Ordering)
-> Proxy X () () EigenstratSnpEntry m ()
-> Proxy X () () (EigenstratSnpEntry, GenoLine) m [()]
-> Producer
     (Maybe EigenstratSnpEntry, Maybe (EigenstratSnpEntry, GenoLine))
     m
     ((), [()])
forall (m :: * -> *) a b r1 r2.
Monad m =>
(a -> b -> Ordering)
-> Producer a m r1
-> Producer b m r2
-> Producer (Maybe a, Maybe b) m (r1, r2)
orderedZip EigenstratSnpEntry -> (EigenstratSnpEntry, GenoLine) -> Ordering
compFunc2 Proxy X () () EigenstratSnpEntry m ()
snpProd Proxy X () () (EigenstratSnpEntry, GenoLine) m [()]
prod Producer
  (Maybe EigenstratSnpEntry, Maybe (EigenstratSnpEntry, GenoLine))
  m
  ((), [()])
-> Proxy
     X
     ()
     ()
     (Maybe EigenstratSnpEntry, Maybe (EigenstratSnpEntry, GenoLine))
     m
     [()]
-> Proxy
     X
     ()
     ()
     (Maybe EigenstratSnpEntry, Maybe (EigenstratSnpEntry, GenoLine))
     m
     [()]
forall a b.
Proxy
  X
  ()
  ()
  (Maybe EigenstratSnpEntry, Maybe (EigenstratSnpEntry, GenoLine))
  m
  a
-> Proxy
     X
     ()
     ()
     (Maybe EigenstratSnpEntry, Maybe (EigenstratSnpEntry, GenoLine))
     m
     b
-> Proxy
     X
     ()
     ()
     (Maybe EigenstratSnpEntry, Maybe (EigenstratSnpEntry, GenoLine))
     m
     b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> [()]
-> Proxy
     X
     ()
     ()
     (Maybe EigenstratSnpEntry, Maybe (EigenstratSnpEntry, GenoLine))
     m
     [()]
forall a.
a
-> Proxy
     X
     ()
     ()
     (Maybe EigenstratSnpEntry, Maybe (EigenstratSnpEntry, GenoLine))
     m
     a
forall (m :: * -> *) a. Monad m => a -> m a
return [()]) Proxy
  X
  ()
  ()
  (Maybe EigenstratSnpEntry, Maybe (EigenstratSnpEntry, GenoLine))
  m
  [()]
-> Proxy
     ()
     (Maybe EigenstratSnpEntry, Maybe (EigenstratSnpEntry, GenoLine))
     ()
     (EigenstratSnpEntry, GenoLine)
     m
     [()]
-> Proxy X () () (EigenstratSnpEntry, GenoLine) m [()]
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
>-> Int
-> Proxy
     ()
     (Maybe EigenstratSnpEntry, Maybe (EigenstratSnpEntry, GenoLine))
     ()
     (EigenstratSnpEntry, GenoLine)
     m
     [()]
forall (m :: * -> *) r.
Monad m =>
Int
-> Pipe
     (Maybe EigenstratSnpEntry, Maybe (EigenstratSnpEntry, GenoLine))
     (EigenstratSnpEntry, GenoLine)
     m
     r
selectSnps ([Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Int]
nrInds)
    ([EigenstratIndEntry],
 Producer (EigenstratSnpEntry, GenoLine) m ())
-> m ([EigenstratIndEntry],
      Producer (EigenstratSnpEntry, GenoLine) m ())
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ([EigenstratIndEntry]
jointIndEntries, Proxy X () () (EigenstratSnpEntry, GenoLine) m [()]
-> Producer (EigenstratSnpEntry, GenoLine) m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void Proxy X () () (EigenstratSnpEntry, GenoLine) m [()]
jointProducer)
  where
    compFunc :: (EigenstratSnpEntry, GenoLine) -> (EigenstratSnpEntry, GenoLine) -> Ordering
    compFunc :: (EigenstratSnpEntry, GenoLine)
-> (EigenstratSnpEntry, GenoLine) -> Ordering
compFunc (EigenstratSnpEntry Chrom
c1 Int
p1 Double
_ ByteString
_ Char
_ Char
_, GenoLine
_) (EigenstratSnpEntry Chrom
c2 Int
p2 Double
_ ByteString
_ Char
_ Char
_, GenoLine
_) = (Chrom, Int) -> (Chrom, Int) -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Chrom
c1, Int
p1) (Chrom
c2, Int
p2)
    compFunc2 :: EigenstratSnpEntry -> (EigenstratSnpEntry, GenoLine) -> Ordering
    compFunc2 :: EigenstratSnpEntry -> (EigenstratSnpEntry, GenoLine) -> Ordering
compFunc2 (EigenstratSnpEntry Chrom
c1 Int
p1 Double
_ ByteString
_ Char
_ Char
_) (EigenstratSnpEntry Chrom
c2 Int
p2 Double
_ ByteString
_ Char
_ Char
_, GenoLine
_) = (Chrom, Int) -> (Chrom, Int) -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Chrom
c1, Int
p1) (Chrom
c2, Int
p2)
    compFunc3 :: EigenstratSnpEntry -> EigenstratSnpEntry -> Ordering
    compFunc3 :: EigenstratSnpEntry -> EigenstratSnpEntry -> Ordering
compFunc3 (EigenstratSnpEntry Chrom
c1 Int
p1 Double
_ ByteString
_ Char
_ Char
_) (EigenstratSnpEntry Chrom
c2 Int
p2 Double
_ ByteString
_ Char
_ Char
_) = (Chrom, Int) -> (Chrom, Int) -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Chrom
c1, Int
p1) (Chrom
c2, Int
p2)
    filterUnionOrIntersection :: [Maybe (EigenstratSnpEntry, GenoLine)] -> Bool
    filterUnionOrIntersection :: [Maybe (EigenstratSnpEntry, GenoLine)] -> Bool
filterUnionOrIntersection [Maybe (EigenstratSnpEntry, GenoLine)]
maybeTuples = Bool -> Bool
not Bool
intersect Bool -> Bool -> Bool
|| Bool -> Bool
not ((Maybe (EigenstratSnpEntry, GenoLine) -> Bool)
-> [Maybe (EigenstratSnpEntry, GenoLine)] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any Maybe (EigenstratSnpEntry, GenoLine) -> Bool
forall a. Maybe a -> Bool
isNothing [Maybe (EigenstratSnpEntry, GenoLine)]
maybeTuples)
    selectSnps :: (Monad m) => Int -> Pipe (Maybe EigenstratSnpEntry, Maybe (EigenstratSnpEntry, GenoLine)) (EigenstratSnpEntry, GenoLine) m r
    selectSnps :: forall (m :: * -> *) r.
Monad m =>
Int
-> Pipe
     (Maybe EigenstratSnpEntry, Maybe (EigenstratSnpEntry, GenoLine))
     (EigenstratSnpEntry, GenoLine)
     m
     r
selectSnps Int
n = Proxy
  ()
  (Maybe EigenstratSnpEntry, Maybe (EigenstratSnpEntry, GenoLine))
  ()
  (Maybe EigenstratSnpEntry, Maybe (EigenstratSnpEntry, GenoLine))
  m
  r
-> ((Maybe EigenstratSnpEntry,
     Maybe (EigenstratSnpEntry, GenoLine))
    -> Proxy
         ()
         (Maybe EigenstratSnpEntry, Maybe (EigenstratSnpEntry, GenoLine))
         ()
         (EigenstratSnpEntry, GenoLine)
         m
         ())
-> Proxy
     ()
     (Maybe EigenstratSnpEntry, Maybe (EigenstratSnpEntry, GenoLine))
     ()
     (EigenstratSnpEntry, GenoLine)
     m
     r
forall (m :: * -> *) x' x b' b a' c' c.
Functor m =>
Proxy x' x b' b m a'
-> (b -> Proxy x' x c' c m b') -> Proxy x' x c' c m a'
for Proxy
  ()
  (Maybe EigenstratSnpEntry, Maybe (EigenstratSnpEntry, GenoLine))
  ()
  (Maybe EigenstratSnpEntry, Maybe (EigenstratSnpEntry, GenoLine))
  m
  r
forall (m :: * -> *) a r. Functor m => Pipe a a m r
cat (((Maybe EigenstratSnpEntry, Maybe (EigenstratSnpEntry, GenoLine))
  -> Proxy
       ()
       (Maybe EigenstratSnpEntry, Maybe (EigenstratSnpEntry, GenoLine))
       ()
       (EigenstratSnpEntry, GenoLine)
       m
       ())
 -> Proxy
      ()
      (Maybe EigenstratSnpEntry, Maybe (EigenstratSnpEntry, GenoLine))
      ()
      (EigenstratSnpEntry, GenoLine)
      m
      r)
-> ((Maybe EigenstratSnpEntry,
     Maybe (EigenstratSnpEntry, GenoLine))
    -> Proxy
         ()
         (Maybe EigenstratSnpEntry, Maybe (EigenstratSnpEntry, GenoLine))
         ()
         (EigenstratSnpEntry, GenoLine)
         m
         ())
-> Proxy
     ()
     (Maybe EigenstratSnpEntry, Maybe (EigenstratSnpEntry, GenoLine))
     ()
     (EigenstratSnpEntry, GenoLine)
     m
     r
forall a b. (a -> b) -> a -> b
$ \case
        (Just EigenstratSnpEntry
_, Just (EigenstratSnpEntry
es, GenoLine
gl)) -> (EigenstratSnpEntry, GenoLine)
-> Proxy
     ()
     (Maybe EigenstratSnpEntry, Maybe (EigenstratSnpEntry, GenoLine))
     ()
     (EigenstratSnpEntry, GenoLine)
     m
     ()
forall (m :: * -> *) a x' x. Functor m => a -> Proxy x' x () a m ()
yield (EigenstratSnpEntry
es, GenoLine
gl)
        (Just EigenstratSnpEntry
snp, Maybe (EigenstratSnpEntry, GenoLine)
Nothing) -> Bool
-> Proxy
     ()
     (Maybe EigenstratSnpEntry, Maybe (EigenstratSnpEntry, GenoLine))
     ()
     (EigenstratSnpEntry, GenoLine)
     m
     ()
-> Proxy
     ()
     (Maybe EigenstratSnpEntry, Maybe (EigenstratSnpEntry, GenoLine))
     ()
     (EigenstratSnpEntry, GenoLine)
     m
     ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
intersect (Proxy
   ()
   (Maybe EigenstratSnpEntry, Maybe (EigenstratSnpEntry, GenoLine))
   ()
   (EigenstratSnpEntry, GenoLine)
   m
   ()
 -> Proxy
      ()
      (Maybe EigenstratSnpEntry, Maybe (EigenstratSnpEntry, GenoLine))
      ()
      (EigenstratSnpEntry, GenoLine)
      m
      ())
-> Proxy
     ()
     (Maybe EigenstratSnpEntry, Maybe (EigenstratSnpEntry, GenoLine))
     ()
     (EigenstratSnpEntry, GenoLine)
     m
     ()
-> Proxy
     ()
     (Maybe EigenstratSnpEntry, Maybe (EigenstratSnpEntry, GenoLine))
     ()
     (EigenstratSnpEntry, GenoLine)
     m
     ()
forall a b. (a -> b) -> a -> b
$ (EigenstratSnpEntry, GenoLine)
-> Proxy
     ()
     (Maybe EigenstratSnpEntry, Maybe (EigenstratSnpEntry, GenoLine))
     ()
     (EigenstratSnpEntry, GenoLine)
     m
     ()
forall (m :: * -> *) a x' x. Functor m => a -> Proxy x' x () a m ()
yield (EigenstratSnpEntry
snp, Int -> GenoEntry -> GenoLine
forall a. Int -> a -> Vector a
V.replicate Int
n GenoEntry
Missing)
        (Maybe EigenstratSnpEntry, Maybe (EigenstratSnpEntry, GenoLine))
_ ->  ()
-> Proxy
     ()
     (Maybe EigenstratSnpEntry, Maybe (EigenstratSnpEntry, GenoLine))
     ()
     (EigenstratSnpEntry, GenoLine)
     m
     ()
forall a.
a
-> Proxy
     ()
     (Maybe EigenstratSnpEntry, Maybe (EigenstratSnpEntry, GenoLine))
     ()
     (EigenstratSnpEntry, GenoLine)
     m
     a
forall (m :: * -> *) a. Monad m => a -> m a
return ()

getJointJanno :: [PoseidonPackage] -> JannoRows
getJointJanno :: [PoseidonPackage] -> JannoRows
getJointJanno [PoseidonPackage]
pacs = [JannoRows] -> JannoRows
forall a. Monoid a => [a] -> a
mconcat ([JannoRows] -> JannoRows) -> [JannoRows] -> JannoRows
forall a b. (a -> b) -> a -> b
$ (PoseidonPackage -> JannoRows) -> [PoseidonPackage] -> [JannoRows]
forall a b. (a -> b) -> [a] -> [b]
map PoseidonPackage -> JannoRows
posPacJanno [PoseidonPackage]
pacs

getJannoRowsFromPac :: PoseidonPackage -> [JannoRow]
getJannoRowsFromPac :: PoseidonPackage -> [JannoRow]
getJannoRowsFromPac PoseidonPackage
pac = let (JannoRows [JannoRow]
rows) = PoseidonPackage -> JannoRows
posPacJanno PoseidonPackage
pac in [JannoRow]
rows

-- | A pipe to merge the genotype entries from multiple packages.
-- Uses the `joinEntries` function and catches exceptions to skip the respective SNPs.
joinEntryPipe :: (MonadIO m) => LogA -> [Int] -> [String] -> Pipe [Maybe (EigenstratSnpEntry, GenoLine)] (EigenstratSnpEntry, GenoLine) m r
joinEntryPipe :: forall (m :: * -> *) r.
MonadIO m =>
LogA
-> [Int]
-> [FilePath]
-> Pipe
     [Maybe (EigenstratSnpEntry, GenoLine)]
     (EigenstratSnpEntry, GenoLine)
     m
     r
joinEntryPipe LogA
logA [Int]
nrInds [FilePath]
pacNames = Proxy
  ()
  [Maybe (EigenstratSnpEntry, GenoLine)]
  ()
  [Maybe (EigenstratSnpEntry, GenoLine)]
  m
  r
-> ([Maybe (EigenstratSnpEntry, GenoLine)]
    -> Proxy
         ()
         [Maybe (EigenstratSnpEntry, GenoLine)]
         ()
         (EigenstratSnpEntry, GenoLine)
         m
         ())
-> Proxy
     ()
     [Maybe (EigenstratSnpEntry, GenoLine)]
     ()
     (EigenstratSnpEntry, GenoLine)
     m
     r
forall (m :: * -> *) x' x b' b a' c' c.
Functor m =>
Proxy x' x b' b m a'
-> (b -> Proxy x' x c' c m b') -> Proxy x' x c' c m a'
for Proxy
  ()
  [Maybe (EigenstratSnpEntry, GenoLine)]
  ()
  [Maybe (EigenstratSnpEntry, GenoLine)]
  m
  r
forall (m :: * -> *) a r. Functor m => Pipe a a m r
cat (([Maybe (EigenstratSnpEntry, GenoLine)]
  -> Proxy
       ()
       [Maybe (EigenstratSnpEntry, GenoLine)]
       ()
       (EigenstratSnpEntry, GenoLine)
       m
       ())
 -> Proxy
      ()
      [Maybe (EigenstratSnpEntry, GenoLine)]
      ()
      (EigenstratSnpEntry, GenoLine)
      m
      r)
-> ([Maybe (EigenstratSnpEntry, GenoLine)]
    -> Proxy
         ()
         [Maybe (EigenstratSnpEntry, GenoLine)]
         ()
         (EigenstratSnpEntry, GenoLine)
         m
         ())
-> Proxy
     ()
     [Maybe (EigenstratSnpEntry, GenoLine)]
     ()
     (EigenstratSnpEntry, GenoLine)
     m
     r
forall a b. (a -> b) -> a -> b
$ \[Maybe (EigenstratSnpEntry, GenoLine)]
maybeEntries -> do
    Either PoseidonException (EigenstratSnpEntry, GenoLine)
eitherJE <- IO (Either PoseidonException (EigenstratSnpEntry, GenoLine))
-> Proxy
     ()
     [Maybe (EigenstratSnpEntry, GenoLine)]
     ()
     (EigenstratSnpEntry, GenoLine)
     m
     (Either PoseidonException (EigenstratSnpEntry, GenoLine))
forall a.
IO a
-> Proxy
     ()
     [Maybe (EigenstratSnpEntry, GenoLine)]
     ()
     (EigenstratSnpEntry, GenoLine)
     m
     a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Either PoseidonException (EigenstratSnpEntry, GenoLine))
 -> Proxy
      ()
      [Maybe (EigenstratSnpEntry, GenoLine)]
      ()
      (EigenstratSnpEntry, GenoLine)
      m
      (Either PoseidonException (EigenstratSnpEntry, GenoLine)))
-> (IO (EigenstratSnpEntry, GenoLine)
    -> IO (Either PoseidonException (EigenstratSnpEntry, GenoLine)))
-> IO (EigenstratSnpEntry, GenoLine)
-> Proxy
     ()
     [Maybe (EigenstratSnpEntry, GenoLine)]
     ()
     (EigenstratSnpEntry, GenoLine)
     m
     (Either PoseidonException (EigenstratSnpEntry, GenoLine))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO (EigenstratSnpEntry, GenoLine)
-> IO (Either PoseidonException (EigenstratSnpEntry, GenoLine))
forall (m :: * -> *) e a.
(MonadCatch m, Exception e) =>
m a -> m (Either e a)
try (IO (EigenstratSnpEntry, GenoLine)
 -> Proxy
      ()
      [Maybe (EigenstratSnpEntry, GenoLine)]
      ()
      (EigenstratSnpEntry, GenoLine)
      m
      (Either PoseidonException (EigenstratSnpEntry, GenoLine)))
-> IO (EigenstratSnpEntry, GenoLine)
-> Proxy
     ()
     [Maybe (EigenstratSnpEntry, GenoLine)]
     ()
     (EigenstratSnpEntry, GenoLine)
     m
     (Either PoseidonException (EigenstratSnpEntry, GenoLine))
forall a b. (a -> b) -> a -> b
$ LogA
-> [Int]
-> [FilePath]
-> [Maybe (EigenstratSnpEntry, GenoLine)]
-> IO (EigenstratSnpEntry, GenoLine)
forall (m :: * -> *).
MonadIO m =>
LogA
-> [Int]
-> [FilePath]
-> [Maybe (EigenstratSnpEntry, GenoLine)]
-> m (EigenstratSnpEntry, GenoLine)
joinEntries LogA
logA [Int]
nrInds [FilePath]
pacNames [Maybe (EigenstratSnpEntry, GenoLine)]
maybeEntries
    case Either PoseidonException (EigenstratSnpEntry, GenoLine)
eitherJE of
        Left (PoseidonGenotypeException FilePath
err) ->
            LogA
-> PoseidonIO ()
-> Proxy
     ()
     [Maybe (EigenstratSnpEntry, GenoLine)]
     ()
     (EigenstratSnpEntry, GenoLine)
     m
     ()
forall (m :: * -> *). MonadIO m => LogA -> PoseidonIO () -> m ()
logWithEnv LogA
logA (PoseidonIO ()
 -> Proxy
      ()
      [Maybe (EigenstratSnpEntry, GenoLine)]
      ()
      (EigenstratSnpEntry, GenoLine)
      m
      ())
-> (FilePath -> PoseidonIO ())
-> FilePath
-> Proxy
     ()
     [Maybe (EigenstratSnpEntry, GenoLine)]
     ()
     (EigenstratSnpEntry, GenoLine)
     m
     ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> PoseidonIO ()
logDebug (FilePath
 -> Proxy
      ()
      [Maybe (EigenstratSnpEntry, GenoLine)]
      ()
      (EigenstratSnpEntry, GenoLine)
      m
      ())
-> FilePath
-> Proxy
     ()
     [Maybe (EigenstratSnpEntry, GenoLine)]
     ()
     (EigenstratSnpEntry, GenoLine)
     m
     ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Skipping SNP due to " FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ FilePath
err
        Left PoseidonException
e -> IO ()
-> Proxy
     ()
     [Maybe (EigenstratSnpEntry, GenoLine)]
     ()
     (EigenstratSnpEntry, GenoLine)
     m
     ()
forall a.
IO a
-> Proxy
     ()
     [Maybe (EigenstratSnpEntry, GenoLine)]
     ()
     (EigenstratSnpEntry, GenoLine)
     m
     a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO ()
 -> Proxy
      ()
      [Maybe (EigenstratSnpEntry, GenoLine)]
      ()
      (EigenstratSnpEntry, GenoLine)
      m
      ())
-> (PoseidonException -> IO ())
-> PoseidonException
-> Proxy
     ()
     [Maybe (EigenstratSnpEntry, GenoLine)]
     ()
     (EigenstratSnpEntry, GenoLine)
     m
     ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PoseidonException -> IO ()
forall e a. Exception e => e -> IO a
throwIO (PoseidonException
 -> Proxy
      ()
      [Maybe (EigenstratSnpEntry, GenoLine)]
      ()
      (EigenstratSnpEntry, GenoLine)
      m
      ())
-> PoseidonException
-> Proxy
     ()
     [Maybe (EigenstratSnpEntry, GenoLine)]
     ()
     (EigenstratSnpEntry, GenoLine)
     m
     ()
forall a b. (a -> b) -> a -> b
$ PoseidonException
e
        Right (EigenstratSnpEntry
eigenstratSnpEntry, GenoLine
genoLine) -> (EigenstratSnpEntry, GenoLine)
-> Proxy
     ()
     [Maybe (EigenstratSnpEntry, GenoLine)]
     ()
     (EigenstratSnpEntry, GenoLine)
     m
     ()
forall (m :: * -> *) a x' x. Functor m => a -> Proxy x' x () a m ()
yield (EigenstratSnpEntry
eigenstratSnpEntry, GenoLine
genoLine)

loadBimOrSnpFile :: (MonadSafe m) => FilePath -> Producer EigenstratSnpEntry m ()
loadBimOrSnpFile :: forall (m :: * -> *).
MonadSafe m =>
FilePath -> Producer EigenstratSnpEntry m ()
loadBimOrSnpFile FilePath
fn
    | ShowS
takeExtension FilePath
fn FilePath -> [FilePath] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [FilePath
".snp", FilePath
".snp.gz"] = FilePath -> Producer EigenstratSnpEntry m ()
forall (m :: * -> *).
MonadSafe m =>
FilePath -> Producer EigenstratSnpEntry m ()
readEigenstratSnpFile FilePath
fn
    | ShowS
takeExtension FilePath
fn FilePath -> [FilePath] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [FilePath
".bim", FilePath
".bim.gz"] = FilePath -> Producer EigenstratSnpEntry m ()
forall (m :: * -> *).
MonadSafe m =>
FilePath -> Producer EigenstratSnpEntry m ()
readBimFile FilePath
fn
    | Bool
otherwise                  = PoseidonException -> Producer EigenstratSnpEntry m ()
forall e a.
Exception e =>
e -> Proxy X () () EigenstratSnpEntry m a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (FilePath -> PoseidonException
PoseidonGenotypeException FilePath
"option snpFile requires file endings to be *.snp or *.bim or *.snp.gz or *.bim.gz")

-- | A function to create a minimal POSEIDON package
newMinimalPackageTemplate :: FilePath -> String -> GenotypeDataSpec -> PoseidonPackage
newMinimalPackageTemplate :: FilePath -> FilePath -> GenotypeDataSpec -> PoseidonPackage
newMinimalPackageTemplate FilePath
baseDir FilePath
name (GenotypeDataSpec GenotypeFormatSpec
format_ FilePath
geno Maybe FilePath
_ FilePath
snp Maybe FilePath
_ FilePath
ind Maybe FilePath
_ Maybe SNPSetSpec
snpSet_) =
    PoseidonPackage {
        posPacBaseDir :: FilePath
posPacBaseDir = FilePath
baseDir
    ,   posPacPoseidonVersion :: Version
posPacPoseidonVersion = PoseidonVersion -> Version
asVersion PoseidonVersion
latestPoseidonVersion
    ,   posPacNameAndVersion :: PacNameAndVersion
posPacNameAndVersion = FilePath -> Maybe Version -> PacNameAndVersion
PacNameAndVersion FilePath
name Maybe Version
forall a. Maybe a
Nothing
    ,   posPacDescription :: Maybe FilePath
posPacDescription = Maybe FilePath
forall a. Maybe a
Nothing
    ,   posPacContributor :: [ContributorSpec]
posPacContributor = []
    ,   posPacLastModified :: Maybe Day
posPacLastModified = Maybe Day
forall a. Maybe a
Nothing
    ,   posPacGenotypeData :: GenotypeDataSpec
posPacGenotypeData = GenotypeFormatSpec
-> FilePath
-> Maybe FilePath
-> FilePath
-> Maybe FilePath
-> FilePath
-> Maybe FilePath
-> Maybe SNPSetSpec
-> GenotypeDataSpec
GenotypeDataSpec GenotypeFormatSpec
format_ (ShowS
takeFileName FilePath
geno) Maybe FilePath
forall a. Maybe a
Nothing (ShowS
takeFileName FilePath
snp) Maybe FilePath
forall a. Maybe a
Nothing (ShowS
takeFileName FilePath
ind) Maybe FilePath
forall a. Maybe a
Nothing Maybe SNPSetSpec
snpSet_
    ,   posPacJannoFile :: Maybe FilePath
posPacJannoFile = Maybe FilePath
forall a. Maybe a
Nothing
    ,   posPacJanno :: JannoRows
posPacJanno = JannoRows
forall a. Monoid a => a
mempty
    ,   posPacJannoFileChkSum :: Maybe FilePath
posPacJannoFileChkSum = Maybe FilePath
forall a. Maybe a
Nothing
    ,   posPacSeqSourceFile :: Maybe FilePath
posPacSeqSourceFile = Maybe FilePath
forall a. Maybe a
Nothing
    ,   posPacSeqSource :: SeqSourceRows
posPacSeqSource = SeqSourceRows
forall a. Monoid a => a
mempty
    ,   posPacSeqSourceFileChkSum :: Maybe FilePath
posPacSeqSourceFileChkSum = Maybe FilePath
forall a. Maybe a
Nothing
    ,   posPacBibFile :: Maybe FilePath
posPacBibFile = Maybe FilePath
forall a. Maybe a
Nothing
    ,   posPacBib :: BibTeX
posPacBib = [] :: BibTeX
    ,   posPacBibFileChkSum :: Maybe FilePath
posPacBibFileChkSum = Maybe FilePath
forall a. Maybe a
Nothing
    ,   posPacReadmeFile :: Maybe FilePath
posPacReadmeFile = Maybe FilePath
forall a. Maybe a
Nothing
    ,   posPacChangelogFile :: Maybe FilePath
posPacChangelogFile = Maybe FilePath
forall a. Maybe a
Nothing
    }

makePseudoPackageFromGenotypeData :: GenotypeDataSpec -> PoseidonIO PoseidonPackage
makePseudoPackageFromGenotypeData :: GenotypeDataSpec -> ReaderT Env IO PoseidonPackage
makePseudoPackageFromGenotypeData (GenotypeDataSpec GenotypeFormatSpec
format_ FilePath
genoFile_ Maybe FilePath
_ FilePath
snpFile_ Maybe FilePath
_ FilePath
indFile_ Maybe FilePath
_ Maybe SNPSetSpec
snpSet_) = do
    let baseDir :: FilePath
baseDir      = FilePath -> FilePath -> ShowS
getBaseDir FilePath
genoFile_ FilePath
snpFile_ FilePath
indFile_
        outInd :: FilePath
outInd       = ShowS
takeFileName FilePath
indFile_
        outSnp :: FilePath
outSnp       = ShowS
takeFileName FilePath
snpFile_
        outGeno :: FilePath
outGeno      = ShowS
takeFileName FilePath
genoFile_
        genotypeData :: GenotypeDataSpec
genotypeData = GenotypeFormatSpec
-> FilePath
-> Maybe FilePath
-> FilePath
-> Maybe FilePath
-> FilePath
-> Maybe FilePath
-> Maybe SNPSetSpec
-> GenotypeDataSpec
GenotypeDataSpec GenotypeFormatSpec
format_ FilePath
outGeno Maybe FilePath
forall a. Maybe a
Nothing FilePath
outSnp Maybe FilePath
forall a. Maybe a
Nothing FilePath
outInd Maybe FilePath
forall a. Maybe a
Nothing Maybe SNPSetSpec
snpSet_
        pacName :: FilePath
pacName      = ShowS
takeBaseName FilePath
genoFile_
    [EigenstratIndEntry]
inds <- FilePath -> GenotypeDataSpec -> PoseidonIO [EigenstratIndEntry]
loadIndividuals FilePath
baseDir GenotypeDataSpec
genotypeData
    FilePath
-> FilePath
-> GenotypeDataSpec
-> Maybe (Either [EigenstratIndEntry] JannoRows)
-> SeqSourceRows
-> BibTeX
-> ReaderT Env IO PoseidonPackage
newPackageTemplate FilePath
baseDir FilePath
pacName GenotypeDataSpec
genotypeData (Either [EigenstratIndEntry] JannoRows
-> Maybe (Either [EigenstratIndEntry] JannoRows)
forall a. a -> Maybe a
Just ([EigenstratIndEntry] -> Either [EigenstratIndEntry] JannoRows
forall a b. a -> Either a b
Left [EigenstratIndEntry]
inds)) SeqSourceRows
forall a. Monoid a => a
mempty []
    where
        getBaseDir :: FilePath -> FilePath -> FilePath -> FilePath
        getBaseDir :: FilePath -> FilePath -> ShowS
getBaseDir FilePath
g FilePath
s FilePath
i =
            let baseDirGeno :: FilePath
baseDirGeno = ShowS
takeDirectory FilePath
genoFile_
                baseDirSnp :: FilePath
baseDirSnp = ShowS
takeDirectory FilePath
snpFile_
                baseDirInd :: FilePath
baseDirInd = ShowS
takeDirectory FilePath
indFile_
            in if FilePath
baseDirGeno FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
== FilePath
baseDirSnp Bool -> Bool -> Bool
&& FilePath
baseDirSnp FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
== FilePath
baseDirInd
               then FilePath
baseDirGeno
               else PoseidonException -> FilePath
forall e a. Exception e => e -> [a]
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (PoseidonException -> FilePath) -> PoseidonException -> FilePath
forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath -> FilePath -> PoseidonException
PoseidonUnequalBaseDirException FilePath
g FilePath
s FilePath
i

-- | A function to create a more complete POSEIDON package
-- This will take only the filenames of the provided files, so it assumes that the files will be copied into
-- the directory into which the YAML file will be written
newPackageTemplate ::
       FilePath
    -> String
    -> GenotypeDataSpec
    -> Maybe (Either [EigenstratIndEntry] JannoRows)
    -> SeqSourceRows
    -> BibTeX
    -> PoseidonIO PoseidonPackage
newPackageTemplate :: FilePath
-> FilePath
-> GenotypeDataSpec
-> Maybe (Either [EigenstratIndEntry] JannoRows)
-> SeqSourceRows
-> BibTeX
-> ReaderT Env IO PoseidonPackage
newPackageTemplate FilePath
baseDir FilePath
name GenotypeDataSpec
genoData Maybe (Either [EigenstratIndEntry] JannoRows)
indsOrJanno SeqSourceRows
seqSource BibTeX
bib = do
    (UTCTime Day
today DiffTime
_) <- 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
    let minimalTemplate :: PoseidonPackage
minimalTemplate = FilePath -> FilePath -> GenotypeDataSpec -> PoseidonPackage
newMinimalPackageTemplate FilePath
baseDir FilePath
name GenotypeDataSpec
genoData
        fluffedUpTemplate :: PoseidonPackage
fluffedUpTemplate = PoseidonPackage
minimalTemplate {
            posPacDescription :: Maybe FilePath
posPacDescription = FilePath -> Maybe FilePath
forall a. a -> Maybe a
Just FilePath
"Empty package template. Please add a description"
        ,   posPacContributor :: [ContributorSpec]
posPacContributor = []
        ,   posPacNameAndVersion :: PacNameAndVersion
posPacNameAndVersion = FilePath -> Maybe Version -> PacNameAndVersion
PacNameAndVersion FilePath
name (Version -> Maybe Version
forall a. a -> Maybe a
Just (Version -> Maybe Version) -> Version -> Maybe Version
forall a b. (a -> b) -> a -> b
$ [Int] -> Version
makeVersion [Int
0, Int
1, Int
0])
        ,   posPacLastModified :: Maybe Day
posPacLastModified = Day -> Maybe Day
forall a. a -> Maybe a
Just Day
today
        }
        jannoFilledTemplate :: PoseidonPackage
jannoFilledTemplate     = FilePath
-> Maybe (Either [EigenstratIndEntry] JannoRows)
-> PoseidonPackage
-> PoseidonPackage
completeJannoSpec FilePath
name Maybe (Either [EigenstratIndEntry] JannoRows)
indsOrJanno PoseidonPackage
fluffedUpTemplate
        seqSourceFilledTemplate :: PoseidonPackage
seqSourceFilledTemplate = FilePath -> SeqSourceRows -> PoseidonPackage -> PoseidonPackage
completeSeqSourceSpec FilePath
name SeqSourceRows
seqSource PoseidonPackage
jannoFilledTemplate
        bibFilledTemplate :: PoseidonPackage
bibFilledTemplate       = FilePath -> BibTeX -> PoseidonPackage -> PoseidonPackage
completeBibSpec FilePath
name BibTeX
bib PoseidonPackage
seqSourceFilledTemplate
    PoseidonPackage -> ReaderT Env IO PoseidonPackage
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return PoseidonPackage
bibFilledTemplate
    where
        completeJannoSpec :: FilePath
-> Maybe (Either [EigenstratIndEntry] JannoRows)
-> PoseidonPackage
-> PoseidonPackage
completeJannoSpec FilePath
_ Maybe (Either [EigenstratIndEntry] JannoRows)
Nothing PoseidonPackage
inTemplate = PoseidonPackage
inTemplate
        completeJannoSpec FilePath
name_ (Just (Left [EigenstratIndEntry]
a)) PoseidonPackage
inTemplate =
            PoseidonPackage
inTemplate {
                posPacJannoFile :: Maybe FilePath
posPacJannoFile = FilePath -> Maybe FilePath
forall a. a -> Maybe a
Just (FilePath -> Maybe FilePath) -> FilePath -> Maybe FilePath
forall a b. (a -> b) -> a -> b
$ FilePath
name_ FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ FilePath
".janno",
                posPacJanno :: JannoRows
posPacJanno = [EigenstratIndEntry] -> JannoRows
createMinimalJanno [EigenstratIndEntry]
a
            }
        completeJannoSpec FilePath
name_ (Just (Right JannoRows
b)) PoseidonPackage
inTemplate =
            PoseidonPackage
inTemplate {
                posPacJannoFile :: Maybe FilePath
posPacJannoFile = FilePath -> Maybe FilePath
forall a. a -> Maybe a
Just (FilePath -> Maybe FilePath) -> FilePath -> Maybe FilePath
forall a b. (a -> b) -> a -> b
$ FilePath
name_ FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ FilePath
".janno",
                posPacJanno :: JannoRows
posPacJanno = JannoRows
b
            }
        completeSeqSourceSpec :: FilePath -> SeqSourceRows -> PoseidonPackage -> PoseidonPackage
completeSeqSourceSpec FilePath
_ (SeqSourceRows []) PoseidonPackage
inTemplate = PoseidonPackage
inTemplate
        completeSeqSourceSpec FilePath
name_ SeqSourceRows
xs PoseidonPackage
inTemplate =
            PoseidonPackage
inTemplate {
                posPacSeqSourceFile :: Maybe FilePath
posPacSeqSourceFile = FilePath -> Maybe FilePath
forall a. a -> Maybe a
Just (FilePath -> Maybe FilePath) -> FilePath -> Maybe FilePath
forall a b. (a -> b) -> a -> b
$ FilePath
name_ FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ FilePath
".ssf",
                posPacSeqSource :: SeqSourceRows
posPacSeqSource = SeqSourceRows
xs
            }
        completeBibSpec :: FilePath -> BibTeX -> PoseidonPackage -> PoseidonPackage
completeBibSpec FilePath
_ [] PoseidonPackage
inTemplate = PoseidonPackage
inTemplate
        completeBibSpec FilePath
name_ BibTeX
xs PoseidonPackage
inTemplate =
            PoseidonPackage
inTemplate {
                posPacBibFile :: Maybe FilePath
posPacBibFile = FilePath -> Maybe FilePath
forall a. a -> Maybe a
Just (FilePath -> Maybe FilePath) -> FilePath -> Maybe FilePath
forall a b. (a -> b) -> a -> b
$ FilePath
name_ FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ FilePath
".bib",
                posPacBib :: BibTeX
posPacBib = BibTeX
xs
            }

writePoseidonPackage :: PoseidonPackage -> IO ()
writePoseidonPackage :: PoseidonPackage -> IO ()
writePoseidonPackage (PoseidonPackage FilePath
baseDir Version
ver PacNameAndVersion
nameAndVer Maybe FilePath
des [ContributorSpec]
con Maybe Day
mod_ GenotypeDataSpec
geno Maybe FilePath
jannoF JannoRows
_ Maybe FilePath
jannoC Maybe FilePath
seqSourceF SeqSourceRows
_ Maybe FilePath
seqSourceC Maybe FilePath
bibF BibTeX
_ Maybe FilePath
bibFC Maybe FilePath
readF Maybe FilePath
changeF) = do
    let yamlPac :: PoseidonYamlStruct
yamlPac = Version
-> FilePath
-> Maybe FilePath
-> [ContributorSpec]
-> Maybe Version
-> Maybe Day
-> GenotypeDataSpec
-> Maybe FilePath
-> Maybe FilePath
-> Maybe FilePath
-> Maybe FilePath
-> Maybe FilePath
-> Maybe FilePath
-> Maybe FilePath
-> Maybe FilePath
-> PoseidonYamlStruct
PoseidonYamlStruct Version
ver (PacNameAndVersion -> FilePath
forall a. HasNameAndVersion a => a -> FilePath
getPacName PacNameAndVersion
nameAndVer) Maybe FilePath
des [ContributorSpec]
con (PacNameAndVersion -> Maybe Version
forall a. HasNameAndVersion a => a -> Maybe Version
getPacVersion PacNameAndVersion
nameAndVer) Maybe Day
mod_ GenotypeDataSpec
geno Maybe FilePath
jannoF Maybe FilePath
jannoC Maybe FilePath
seqSourceF Maybe FilePath
seqSourceC Maybe FilePath
bibF Maybe FilePath
bibFC Maybe FilePath
readF Maybe FilePath
changeF
        outF :: FilePath
outF = FilePath
baseDir FilePath -> ShowS
</> FilePath
"POSEIDON.yml"
    FilePath -> ByteString -> IO ()
B.writeFile FilePath
outF (ByteString -> IO ()) -> ByteString -> IO ()
forall a b. NFData a => (a -> b) -> a -> b
$!! Config -> PoseidonYamlStruct -> ByteString
forall a. ToJSON a => Config -> a -> ByteString
encodePretty Config
opts PoseidonYamlStruct
yamlPac
    where
        opts :: Config
opts = Bool -> Config -> Config
setConfDropNull Bool
True (Config -> Config) -> Config -> Config
forall a b. (a -> b) -> a -> b
$ (Text -> Text -> Ordering) -> Config -> Config
setConfCompare (Int -> Int -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Int -> Int -> Ordering)
-> (Text -> Int) -> Text -> Text -> Ordering
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` Text -> Int
fieldIndex) Config
defConfig
        fieldIndex :: Text -> Int
fieldIndex Text
s = Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
fromMaybe ([Text] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Text]
fields) (Maybe Int -> Int) -> Maybe Int -> Int
forall a b. (a -> b) -> a -> b
$ Text
s Text -> [Text] -> Maybe Int
forall a. Eq a => a -> [a] -> Maybe Int
`elemIndex` [Text]
fields
        fields :: [Text]
fields = [
          Text
"poseidonVersion",
          Text
"title",
          Text
"description",
          Text
"contributor",
          Text
"name",
          Text
"email",
          Text
"orcid",
          Text
"packageVersion",
          Text
"lastModified",
          Text
"genotypeData",
          Text
"format",
          Text
"genoFile",
          Text
"genoFileChkSum",
          Text
"snpFile",
          Text
"snpFileChkSum",
          Text
"indFile",
          Text
"indFileChkSum",
          Text
"snpSet",
          Text
"jannoFile",
          Text
"jannoFileChkSum",
          Text
"sequencingSourceFile",
          Text
"sequencingSourceFileChkSum",
          Text
"bibFile",
          Text
"bibFileChkSum",
          Text
"readmeFile",
          Text
"changelogFile"
         ]

packagesToPackageInfos :: (MonadThrow m) => [PoseidonPackage] -> m [PackageInfo]
packagesToPackageInfos :: forall (m :: * -> *).
MonadThrow m =>
[PoseidonPackage] -> m [PackageInfo]
packagesToPackageInfos [PoseidonPackage]
pacs = do
    [PoseidonPackage]
-> (PoseidonPackage -> m PackageInfo) -> m [PackageInfo]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [PoseidonPackage]
pacs ((PoseidonPackage -> m PackageInfo) -> m [PackageInfo])
-> (PoseidonPackage -> m PackageInfo) -> m [PackageInfo]
forall a b. (a -> b) -> a -> b
$ \PoseidonPackage
pac -> do
        Bool
isLatest <- [PoseidonPackage] -> PoseidonPackage -> m Bool
forall (m :: * -> *) a.
(MonadThrow m, HasNameAndVersion a) =>
[a] -> a -> m Bool
isLatestInCollection [PoseidonPackage]
pacs PoseidonPackage
pac
        PackageInfo -> m PackageInfo
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (PackageInfo -> m PackageInfo) -> PackageInfo -> m PackageInfo
forall a b. (a -> b) -> a -> b
$ PackageInfo {
            pPac :: PacNameAndVersion
pPac           = PoseidonPackage -> PacNameAndVersion
posPacNameAndVersion PoseidonPackage
pac,
            pIsLatest :: Bool
pIsLatest      = Bool
isLatest,
            pPosVersion :: Version
pPosVersion    = PoseidonPackage -> Version
posPacPoseidonVersion PoseidonPackage
pac,
            pDescription :: Maybe FilePath
pDescription   = PoseidonPackage -> Maybe FilePath
posPacDescription PoseidonPackage
pac,
            pLastModified :: Maybe Day
pLastModified  = PoseidonPackage -> Maybe Day
posPacLastModified PoseidonPackage
pac,
            pNrIndividuals :: Int
pNrIndividuals = ([JannoRow] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([JannoRow] -> Int)
-> (PoseidonPackage -> [JannoRow]) -> PoseidonPackage -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PoseidonPackage -> [JannoRow]
getJannoRowsFromPac) PoseidonPackage
pac
        }

getAllGroupInfo :: (MonadThrow m) => [PoseidonPackage] -> m [GroupInfo]
getAllGroupInfo :: forall (m :: * -> *).
MonadThrow m =>
[PoseidonPackage] -> m [GroupInfo]
getAllGroupInfo [PoseidonPackage]
packages = do
    let individualInfoUnnested :: [(FilePath, PacNameAndVersion)]
individualInfoUnnested = do
            PoseidonPackage
pac <- [PoseidonPackage]
packages
            JannoRow
jannoRow <- PoseidonPackage -> [JannoRow]
getJannoRowsFromPac PoseidonPackage
pac
            let groups :: [FilePath]
groups = JannoList FilePath -> [FilePath]
forall a. JannoList a -> [a]
getJannoList (JannoList FilePath -> [FilePath])
-> (JannoRow -> JannoList FilePath) -> JannoRow -> [FilePath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. JannoRow -> JannoList FilePath
jGroupName (JannoRow -> [FilePath]) -> JannoRow -> [FilePath]
forall a b. (a -> b) -> a -> b
$ JannoRow
jannoRow
            [(FilePath
g, PoseidonPackage -> PacNameAndVersion
forall a. HasNameAndVersion a => a -> PacNameAndVersion
makePacNameAndVersion PoseidonPackage
pac) | FilePath
g <- [FilePath]
groups]
    -- loop over pairs of groups and pacNames
    [[(FilePath, PacNameAndVersion)]]
-> ([(FilePath, PacNameAndVersion)] -> m GroupInfo)
-> m [GroupInfo]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM (([(FilePath, PacNameAndVersion)]
-> [[(FilePath, PacNameAndVersion)]]
forall a. Eq a => [a] -> [[a]]
group ([(FilePath, PacNameAndVersion)]
 -> [[(FilePath, PacNameAndVersion)]])
-> ([(FilePath, PacNameAndVersion)]
    -> [(FilePath, PacNameAndVersion)])
-> [(FilePath, PacNameAndVersion)]
-> [[(FilePath, PacNameAndVersion)]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(FilePath, PacNameAndVersion)] -> [(FilePath, PacNameAndVersion)]
forall a. Ord a => [a] -> [a]
sort) [(FilePath, PacNameAndVersion)]
individualInfoUnnested) (([(FilePath, PacNameAndVersion)] -> m GroupInfo) -> m [GroupInfo])
-> ([(FilePath, PacNameAndVersion)] -> m GroupInfo)
-> m [GroupInfo]
forall a b. (a -> b) -> a -> b
$ \[(FilePath, PacNameAndVersion)]
group_ -> do
        let groupName :: FilePath
groupName   = [FilePath] -> FilePath
forall a. HasCallStack => [a] -> a
head ([FilePath] -> FilePath)
-> ([(FilePath, PacNameAndVersion)] -> [FilePath])
-> [(FilePath, PacNameAndVersion)]
-> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((FilePath, PacNameAndVersion) -> FilePath)
-> [(FilePath, PacNameAndVersion)] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map (FilePath, PacNameAndVersion) -> FilePath
forall a b. (a, b) -> a
fst ([(FilePath, PacNameAndVersion)] -> FilePath)
-> [(FilePath, PacNameAndVersion)] -> FilePath
forall a b. (a -> b) -> a -> b
$ [(FilePath, PacNameAndVersion)]
group_
            groupPac :: PacNameAndVersion
groupPac    = [PacNameAndVersion] -> PacNameAndVersion
forall a. HasCallStack => [a] -> a
head ([PacNameAndVersion] -> PacNameAndVersion)
-> ([(FilePath, PacNameAndVersion)] -> [PacNameAndVersion])
-> [(FilePath, PacNameAndVersion)]
-> PacNameAndVersion
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((FilePath, PacNameAndVersion) -> PacNameAndVersion)
-> [(FilePath, PacNameAndVersion)] -> [PacNameAndVersion]
forall a b. (a -> b) -> [a] -> [b]
map (FilePath, PacNameAndVersion) -> PacNameAndVersion
forall a b. (a, b) -> b
snd ([(FilePath, PacNameAndVersion)] -> PacNameAndVersion)
-> [(FilePath, PacNameAndVersion)] -> PacNameAndVersion
forall a b. (a -> b) -> a -> b
$ [(FilePath, PacNameAndVersion)]
group_
            groupNrInds :: Int
groupNrInds = [(FilePath, PacNameAndVersion)] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(FilePath, PacNameAndVersion)]
group_
        Bool
isLatest <- [PacNameAndVersion] -> PacNameAndVersion -> m Bool
forall (m :: * -> *) a.
(MonadThrow m, HasNameAndVersion a) =>
[a] -> a -> m Bool
isLatestInCollection ((PoseidonPackage -> PacNameAndVersion)
-> [PoseidonPackage] -> [PacNameAndVersion]
forall a b. (a -> b) -> [a] -> [b]
map PoseidonPackage -> PacNameAndVersion
forall a. HasNameAndVersion a => a -> PacNameAndVersion
makePacNameAndVersion [PoseidonPackage]
packages) PacNameAndVersion
groupPac
        GroupInfo -> m GroupInfo
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (GroupInfo -> m GroupInfo) -> GroupInfo -> m GroupInfo
forall a b. (a -> b) -> a -> b
$ FilePath -> PacNameAndVersion -> Bool -> Int -> GroupInfo
GroupInfo FilePath
groupName PacNameAndVersion
groupPac Bool
isLatest Int
groupNrInds

getJointIndividualInfo :: (MonadThrow m) => [PoseidonPackage] -> m IndividualInfoCollection
getJointIndividualInfo :: forall (m :: * -> *).
MonadThrow m =>
[PoseidonPackage] -> m IndividualInfoCollection
getJointIndividualInfo [PoseidonPackage]
packages = do
    [[(IndividualInfo, Bool)]]
indInfoLatestPairs <- [PoseidonPackage]
-> (PoseidonPackage -> m [(IndividualInfo, Bool)])
-> m [[(IndividualInfo, Bool)]]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [PoseidonPackage]
packages ((PoseidonPackage -> m [(IndividualInfo, Bool)])
 -> m [[(IndividualInfo, Bool)]])
-> (PoseidonPackage -> m [(IndividualInfo, Bool)])
-> m [[(IndividualInfo, Bool)]]
forall a b. (a -> b) -> a -> b
$ \PoseidonPackage
pac -> do
        Bool
isLatest <- [PoseidonPackage] -> PoseidonPackage -> m Bool
forall (m :: * -> *) a.
(MonadThrow m, HasNameAndVersion a) =>
[a] -> a -> m Bool
isLatestInCollection [PoseidonPackage]
packages PoseidonPackage
pac
        [JannoRow]
-> (JannoRow -> m (IndividualInfo, Bool))
-> m [(IndividualInfo, Bool)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM (PoseidonPackage -> [JannoRow]
getJannoRowsFromPac PoseidonPackage
pac) ((JannoRow -> m (IndividualInfo, Bool))
 -> m [(IndividualInfo, Bool)])
-> (JannoRow -> m (IndividualInfo, Bool))
-> m [(IndividualInfo, Bool)]
forall a b. (a -> b) -> a -> b
$ \JannoRow
jannoRow -> do
            let indInfo :: IndividualInfo
indInfo = FilePath -> [FilePath] -> PacNameAndVersion -> IndividualInfo
IndividualInfo
                    (JannoRow -> FilePath
jPoseidonID JannoRow
jannoRow)
                    ((JannoList FilePath -> [FilePath]
forall a. JannoList a -> [a]
getJannoList (JannoList FilePath -> [FilePath])
-> (JannoRow -> JannoList FilePath) -> JannoRow -> [FilePath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. JannoRow -> JannoList FilePath
jGroupName) JannoRow
jannoRow)
                    (PoseidonPackage -> PacNameAndVersion
forall a. HasNameAndVersion a => a -> PacNameAndVersion
makePacNameAndVersion PoseidonPackage
pac)
            (IndividualInfo, Bool) -> m (IndividualInfo, Bool)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (IndividualInfo
indInfo, Bool
isLatest)
    IndividualInfoCollection -> m IndividualInfoCollection
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (((IndividualInfo, Bool) -> IndividualInfo)
-> [(IndividualInfo, Bool)] -> [IndividualInfo]
forall a b. (a -> b) -> [a] -> [b]
map (IndividualInfo, Bool) -> IndividualInfo
forall a b. (a, b) -> a
fst ([(IndividualInfo, Bool)] -> [IndividualInfo])
-> ([[(IndividualInfo, Bool)]] -> [(IndividualInfo, Bool)])
-> [[(IndividualInfo, Bool)]]
-> [IndividualInfo]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[(IndividualInfo, Bool)]] -> [(IndividualInfo, Bool)]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[(IndividualInfo, Bool)]] -> [IndividualInfo])
-> [[(IndividualInfo, Bool)]] -> [IndividualInfo]
forall a b. (a -> b) -> a -> b
$ [[(IndividualInfo, Bool)]]
indInfoLatestPairs, ((IndividualInfo, Bool) -> Bool)
-> [(IndividualInfo, Bool)] -> [Bool]
forall a b. (a -> b) -> [a] -> [b]
map (IndividualInfo, Bool) -> Bool
forall a b. (a, b) -> b
snd ([(IndividualInfo, Bool)] -> [Bool])
-> ([[(IndividualInfo, Bool)]] -> [(IndividualInfo, Bool)])
-> [[(IndividualInfo, Bool)]]
-> [Bool]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[(IndividualInfo, Bool)]] -> [(IndividualInfo, Bool)]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[(IndividualInfo, Bool)]] -> [Bool])
-> [[(IndividualInfo, Bool)]] -> [Bool]
forall a b. (a -> b) -> a -> b
$ [[(IndividualInfo, Bool)]]
indInfoLatestPairs)


getExtendedIndividualInfo :: (MonadThrow m) => [PoseidonPackage] -> AddJannoColSpec -> m [ExtendedIndividualInfo]
getExtendedIndividualInfo :: forall (m :: * -> *).
MonadThrow m =>
[PoseidonPackage] -> AddJannoColSpec -> m [ExtendedIndividualInfo]
getExtendedIndividualInfo [PoseidonPackage]
allPackages AddJannoColSpec
addJannoColSpec = [m ExtendedIndividualInfo] -> m [ExtendedIndividualInfo]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
forall (m :: * -> *) a. Monad m => [m a] -> m [a]
sequence ([m ExtendedIndividualInfo] -> m [ExtendedIndividualInfo])
-> [m ExtendedIndividualInfo] -> m [ExtendedIndividualInfo]
forall a b. (a -> b) -> a -> b
$ do -- list monad
    PoseidonPackage
pac <- [PoseidonPackage]
allPackages -- outer loop (automatically concatenating over inner loops)
    JannoRow
jannoRow <- PoseidonPackage -> [JannoRow]
getJannoRowsFromPac PoseidonPackage
pac -- inner loop
    let name :: FilePath
name = JannoRow -> FilePath
jPoseidonID JannoRow
jannoRow
        groups :: [FilePath]
groups = JannoList FilePath -> [FilePath]
forall a. JannoList a -> [a]
getJannoList (JannoList FilePath -> [FilePath])
-> (JannoRow -> JannoList FilePath) -> JannoRow -> [FilePath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. JannoRow -> JannoList FilePath
jGroupName (JannoRow -> [FilePath]) -> JannoRow -> [FilePath]
forall a b. (a -> b) -> a -> b
$ JannoRow
jannoRow
        colNames :: [FilePath]
colNames = case AddJannoColSpec
addJannoColSpec of
            AddJannoColSpec
AddJannoColAll -> [FilePath]
jannoHeaderString [FilePath] -> [FilePath] -> [FilePath]
forall a. Eq a => [a] -> [a] -> [a]
\\ [FilePath
"Poseidon_ID", FilePath
"Group_Name"] -- Nothing means all Janno columns
                                                                          -- except for these two which are already explicit
            AddJannoColList [FilePath]
c  -> [FilePath]
c
        additionalColumnEntries :: [(FilePath, Maybe FilePath)]
additionalColumnEntries = [(FilePath
k, ByteString -> FilePath
BSC.unpack (ByteString -> FilePath) -> Maybe ByteString -> Maybe FilePath
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> JannoRow -> NamedRecord
forall a. ToNamedRecord a => a -> NamedRecord
toNamedRecord JannoRow
jannoRow NamedRecord -> ByteString -> Maybe ByteString
forall k v. (Eq k, Hashable k) => HashMap k v -> k -> Maybe v
HM.!? FilePath -> ByteString
BSC.pack FilePath
k) | FilePath
k <- [FilePath]
colNames]
    Bool
isLatest <- [PoseidonPackage] -> PoseidonPackage -> [Bool]
forall (m :: * -> *) a.
(MonadThrow m, HasNameAndVersion a) =>
[a] -> a -> m Bool
isLatestInCollection [PoseidonPackage]
allPackages PoseidonPackage
pac -- this lives in monad m
    -- double-return for m and then list.
    m ExtendedIndividualInfo -> [m ExtendedIndividualInfo]
forall a. a -> [a]
forall (m :: * -> *) a. Monad m => a -> m a
return (m ExtendedIndividualInfo -> [m ExtendedIndividualInfo])
-> (ExtendedIndividualInfo -> m ExtendedIndividualInfo)
-> ExtendedIndividualInfo
-> [m ExtendedIndividualInfo]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ExtendedIndividualInfo -> m ExtendedIndividualInfo
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (ExtendedIndividualInfo -> [m ExtendedIndividualInfo])
-> ExtendedIndividualInfo -> [m ExtendedIndividualInfo]
forall a b. (a -> b) -> a -> b
$ FilePath
-> [FilePath]
-> PacNameAndVersion
-> Bool
-> [(FilePath, Maybe FilePath)]
-> ExtendedIndividualInfo
ExtendedIndividualInfo FilePath
name [FilePath]
groups (PoseidonPackage -> PacNameAndVersion
forall a. HasNameAndVersion a => a -> PacNameAndVersion
makePacNameAndVersion PoseidonPackage
pac) Bool
isLatest [(FilePath, Maybe FilePath)]
additionalColumnEntries

-- | Filter packages such that only packages with individuals covered by the given EntitySpec are returned
filterToRelevantPackages :: (MonadThrow m) => (EntitySpec a) => [a] -> [PoseidonPackage] -> m [PoseidonPackage]
filterToRelevantPackages :: forall (m :: * -> *) a.
(MonadThrow m, EntitySpec a) =>
[a] -> [PoseidonPackage] -> m [PoseidonPackage]
filterToRelevantPackages [a]
entities [PoseidonPackage]
packages = do
    IndividualInfoCollection
indInfoCollection <- [PoseidonPackage] -> m IndividualInfoCollection
forall (m :: * -> *).
MonadThrow m =>
[PoseidonPackage] -> m IndividualInfoCollection
getJointIndividualInfo [PoseidonPackage]
packages
    [PacNameAndVersion]
relevantPacs <- [a] -> IndividualInfoCollection -> m [PacNameAndVersion]
forall (m :: * -> *) a.
(MonadThrow m, EntitySpec a) =>
[a] -> IndividualInfoCollection -> m [PacNameAndVersion]
determineRelevantPackages [a]
entities IndividualInfoCollection
indInfoCollection
    [PoseidonPackage] -> m [PoseidonPackage]
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ([PoseidonPackage] -> m [PoseidonPackage])
-> [PoseidonPackage] -> m [PoseidonPackage]
forall a b. (a -> b) -> a -> b
$ (PoseidonPackage -> Bool) -> [PoseidonPackage] -> [PoseidonPackage]
forall a. (a -> Bool) -> [a] -> [a]
filter (\PoseidonPackage
p -> PoseidonPackage -> PacNameAndVersion
forall a. HasNameAndVersion a => a -> PacNameAndVersion
makePacNameAndVersion PoseidonPackage
p PacNameAndVersion -> [PacNameAndVersion] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [PacNameAndVersion]
relevantPacs) [PoseidonPackage]
packages