The main function.

    :param argString: the options.

    :type argString: list

    These are the steps of this module:

    1.  Prints the options.
    2.  Finds the overlapping markers between the three reference panels and
        the source panel (:py:func:`findOverlappingSNPsWithReference`).
    3.  Extract the required markers from all the data sets
        (:py:func:`extractSNPs`).
    4.  Renames the reference panel's marker names to that they are the same as
        the source panel (for all populations) (:py:func:`renameSNPs`).
    5.  Combines the three reference panels together
        (:py:func:`combinePlinkBinaryFiles`).
    6.  Compute the frequency of all the markers from the reference and the
        source panels (:py:func:`computeFrequency`).
    7.  Finds the markers to flip in the reference panel (when compared to the
        source panel) (:py:func:`findFlippedSNPs`).
    8.  Excludes the unflippable markers from the reference and the source
        panels (:py:func:`excludeSNPs`).
    9.  Flips the markers that need flipping in their reference panel
        (:py:func:`flipSNPs`).
    10. Combines the reference and the source panels
        (:py:func:`combinePlinkBinaryFiles`).
    11. Runs part of :py:mod:`pyGenClean.RelatedSamples.find_related_samples`
        on the combined data set (:py:func:`runRelatedness`).
    12. Creates the ``mds`` file from the combined data set and the result of
        previous step (:py:func:`createMDSFile`).
    13. Creates the population file (:py:func:`createPopulationFile`).
    14. Plots the ``mds`` values (:py:func:`plotMDS`).
    15. Finds the outliers of a given reference population
        (:py:func:`find_the_outliers`).
    16. If required, computes the Eigenvalues using smartpca
        (:py:func:`compute_eigenvalues`).
    17. If required, creates a scree plot from smartpca resutls
        (:py:func:`create_scree_plot`).

def main(argString=None):
    """The main function.

    :param argString: the options.

    :type argString: list

    These are the steps of this module:

    1.  Prints the options.
    2.  Finds the overlapping markers between the three reference panels and
        the source panel (:py:func:`findOverlappingSNPsWithReference`).
    3.  Extract the required markers from all the data sets
        (:py:func:`extractSNPs`).
    4.  Renames the reference panel's marker names to that they are the same as
        the source panel (for all populations) (:py:func:`renameSNPs`).
    5.  Combines the three reference panels together
        (:py:func:`combinePlinkBinaryFiles`).
    6.  Compute the frequency of all the markers from the reference and the
        source panels (:py:func:`computeFrequency`).
    7.  Finds the markers to flip in the reference panel (when compared to the
        source panel) (:py:func:`findFlippedSNPs`).
    8.  Excludes the unflippable markers from the reference and the source
        panels (:py:func:`excludeSNPs`).
    9.  Flips the markers that need flipping in their reference panel
        (:py:func:`flipSNPs`).
    10. Combines the reference and the source panels
        (:py:func:`combinePlinkBinaryFiles`).
    11. Runs part of :py:mod:`pyGenClean.RelatedSamples.find_related_samples`
        on the combined data set (:py:func:`runRelatedness`).
    12. Creates the ``mds`` file from the combined data set and the result of
        previous step (:py:func:`createMDSFile`).
    13. Creates the population file (:py:func:`createPopulationFile`).
    14. Plots the ``mds`` values (:py:func:`plotMDS`).
    15. Finds the outliers of a given reference population
        (:py:func:`find_the_outliers`).
    16. If required, computes the Eigenvalues using smartpca
        (:py:func:`compute_eigenvalues`).
    17. If required, creates a scree plot from smartpca resutls
        (:py:func:`create_scree_plot`).

    """
    # Getting and checking the options
    args = parseArgs(argString)
    checkArgs(args)

    logger.info("Options used:")
    for key, value in vars(args).iteritems():
        logger.info("  --{} {}".format(key.replace("_", "-"), value))

    newBfile = None
    popNames = ["CEU", "YRI", "JPT-CHB"]
    referencePrefixes = [args.ceu_bfile, args.yri_bfile, args.jpt_chb_bfile]
    if not args.skip_ref_pops:
        # Find overlap with the reference file
        logger.info("Finding overlapping SNPs between reference and "
                    "source panels")
        findOverlappingSNPsWithReference(
            prefix=args.bfile,
            referencePrefixes=referencePrefixes,
            referencePopulations=popNames,
            outPrefix=args.out,
        )

        # Extract the required SNPs using Plink (reference panels)
        logger.info("Extracting overlapping SNPs from the reference panels")
        extractSNPs(
            snpToExtractFileNames=[
                args.out + ".{}_snp_to_extract".format(popName)
                for popName in popNames
            ],
            referencePrefixes=referencePrefixes,
            popNames=popNames,
            outPrefix=args.out + ".reference_panel",
            runSGE=args.sge,
            options=args,
        )

        # Extract the required SNPs using Plink (source panel)
        logger.info("Extracting overlapping SNPs from the source panel")
        extractSNPs(
            snpToExtractFileNames=[args.out + ".source_snp_to_extract"],
            referencePrefixes=[args.bfile],
            popNames=["ALL"],
            outPrefix=args.out + ".source_panel",
            runSGE=False,
            options=args,
        )

        # Renaming the reference file, so that the SNP names are the same
        for pop in popNames:
            logger.info("Renaming reference panel's SNPs {} to match source "
                        "panel".format(pop))
            renameSNPs(
                inPrefix=args.out + ".reference_panel.{}".format(pop),
                updateFileName=args.out + ".{}_update_names".format(pop),
                outPrefix=args.out + ".reference_panel.{}.rename".format(pop),
            )

        # Combining the reference panel
        logger.info("Combining the reference panels")
        combinePlinkBinaryFiles(
            prefixes=[
                args.out + ".reference_panel.{}.rename".format(pop)
                for pop in popNames
            ],
            outPrefix=args.out + ".reference_panel.ALL.rename",
        )

        # Computing the frequency (reference panel)
        logger.info("Computing reference panel frequencies")
        computeFrequency(
            prefix=args.out + ".reference_panel.ALL.rename",
            outPrefix=args.out + ".reference_panel.ALL.rename.frequency",
        )

        # Computing the frequency (source panel)
        logger.info("Computing source panel frequencies")
        computeFrequency(
            prefix=args.out + ".source_panel.ALL",
            outPrefix=args.out + ".source_panel.ALL.frequency",
        )

        # Finding the SNPs to flip and flip them in the reference panel
        logger.info("Finding SNPs to flip or to exclude from reference panel")
        findFlippedSNPs(
            frqFile1=args.out + ".reference_panel.ALL.rename.frequency.frq",
            frqFile2=args.out + ".source_panel.ALL.frequency.frq",
            outPrefix=args.out,
        )

        # Excluding SNPs (reference panel)
        logger.info("Excluding SNPs from reference panel")
        excludeSNPs(
            inPrefix=args.out + ".reference_panel.ALL.rename",
            outPrefix=args.out + ".reference_panel.ALL.rename.cleaned",
            exclusionFileName=args.out + ".snp_to_remove",
        )

        # Excluding SNPs (source panel)
        logger.info("Excluding SNPs from source panel")
        excludeSNPs(args.out + ".source_panel.ALL",
                    args.out + ".source_panel.ALL.cleaned",
                    args.out + ".snp_to_remove")

        # Flipping the SNP that need to be flip in the reference
        logger.info("Flipping SNPs in reference panel")
        flipSNPs(
            inPrefix=args.out + ".reference_panel.ALL.rename.cleaned",
            outPrefix=args.out + ".reference_panel.ALL.rename.cleaned.flipped",
            flipFileName=args.out + ".snp_to_flip_in_reference",
        )

        # Combining the reference panel
        logger.info("Combining reference and source panels")
        combinePlinkBinaryFiles(
            prefixes=[args.out + ".reference_panel.ALL.rename.cleaned.flipped",
                      args.out + ".source_panel.ALL.cleaned"],
            outPrefix=args.out + ".final_dataset_for_genome",
        )

        # Runing the relatedness step
        logger.info("Creating the genome file using Plink")
        newBfile = runRelatedness(
            inputPrefix=args.out + ".final_dataset_for_genome",
            outPrefix=args.out,
            options=args,
        )

    else:
        # Just run relatedness on the dataset
        newBfile = runRelatedness(
            inputPrefix=args.bfile,
            outPrefix=args.out,
            options=args,
        )

    # Creating the MDS file
    logger.info("Creating the MDS file using Plink")
    createMDSFile(
        nb_components=args.nb_components,
        inPrefix=newBfile,
        outPrefix=args.out + ".mds",
        genomeFileName=args.out + ".ibs.genome.genome",
    )

    if not args.skip_ref_pops:
        # Creating the population files
        logger.info("Creating a population file")
        famFiles = [
            args.out + ".reference_panel." + i + ".fam" for i in popNames
        ]
        famFiles.append(args.out + ".source_panel.ALL.fam")
        labels = popNames + ["SOURCE"]
        createPopulationFile(
            inputFiles=famFiles,
            labels=labels,
            outputFileName=args.out + ".population_file",
        )

        # Plot the MDS value
        logger.info("Creating the MDS plot")
        plotMDS(
            inputFileName=args.out + ".mds.mds",
            outPrefix=args.out + ".mds",
            populationFileName=args.out + ".population_file",
            options=args,
        )

        # Finding the outliers
        logger.info("Finding the outliers")
        find_the_outliers(
            mds_file_name=args.out + ".mds.mds",
            population_file_name=args.out + ".population_file",
            ref_pop_name=args.outliers_of,
            multiplier=args.multiplier,
            out_prefix=args.out,
        )

    # De we need to create a scree plot?
    if args.create_scree_plot:
        # Computing the eigenvalues using smartpca
        logger.info("Computing eigenvalues")
        compute_eigenvalues(
            in_prefix=args.out + ".ibs.pruned_data",
            out_prefix=args.out + ".smartpca",
        )

        logger.info("Creating scree plot")
        create_scree_plot(
            in_filename=args.out + ".smartpca.evec.txt",
            out_filename=args.out + ".smartpca.scree_plot.png",
            plot_title=args.scree_plot_title,
        )