Runs step6 (sexcheck).

    :param in_prefix: the prefix of the input files.
    :param in_type: the type of the input files.
    :param out_prefix: the output prefix.
    :param base_dir: the output directory.
    :param options: the options needed.

    :type in_prefix: str
    :type in_type: str
    :type out_prefix: str
    :type base_dir: str
    :type options: list

    :returns: a tuple containing the prefix of the output files (the input
              prefix for the next script) and the type of the output files
              (``bfile``).

    This function calls the :py:mod:`pyGenClean.SexCheck.sex_check` module. The
    required file type for this module is ``bfile``, hence the need to use the
    :py:func:`check_input_files` to check if the file input file type is the
    good one, or to create it if needed.

    .. note::
        The :py:mod:`pyGenClean.SexCheck.sex_check` module doesn't return
        usable output files. Hence, this function returns the input file prefix
        and its type.

def run_sex_check(in_prefix, in_type, out_prefix, base_dir, options):
    """Runs step6 (sexcheck).

    :param in_prefix: the prefix of the input files.
    :param in_type: the type of the input files.
    :param out_prefix: the output prefix.
    :param base_dir: the output directory.
    :param options: the options needed.

    :type in_prefix: str
    :type in_type: str
    :type out_prefix: str
    :type base_dir: str
    :type options: list

    :returns: a tuple containing the prefix of the output files (the input
              prefix for the next script) and the type of the output files
              (``bfile``).

    This function calls the :py:mod:`pyGenClean.SexCheck.sex_check` module. The
    required file type for this module is ``bfile``, hence the need to use the
    :py:func:`check_input_files` to check if the file input file type is the
    good one, or to create it if needed.

    .. note::
        The :py:mod:`pyGenClean.SexCheck.sex_check` module doesn't return
        usable output files. Hence, this function returns the input file prefix
        and its type.

    """
    # Creating the output directory
    os.mkdir(out_prefix)

    # We know we need a bfile
    required_type = "bfile"
    check_input_files(in_prefix, in_type, required_type)

    # We need to inject the name of the input file and the name of the output
    # prefix
    script_prefix = os.path.join(out_prefix, "sexcheck")
    options += ["--{}".format(required_type), in_prefix,
                "--out", script_prefix]

    # We run the script
    try:
        sex_check.main(options)
    except sex_check.ProgramError as e:
        msg = "sex_check {}".format(e)
        raise ProgramError(msg)

    # Reading the hetero file on X
    hetero = {}
    if os.path.isfile(script_prefix + ".chr23_recodeA.raw.hetero"):
        with open(script_prefix + ".chr23_recodeA.raw.hetero", "r") as i_file:
            header = {
                name: i for i, name in
                enumerate(createRowFromPlinkSpacedOutput(i_file.readline()))
            }
            for required_col in ("PED", "ID", "HETERO"):
                if required_col not in header:
                    msg = "{}: no column named {}".format(
                        script_prefix + ".chr23_recodeA.raw.hetero",
                        required_col,
                    )
                    raise ProgramError(msg)

            # Reading the data
            for line in i_file:
                row = line.rstrip("\r\n").split("\t")
                famid = row[header["PED"]]
                indid = row[header["ID"]]

                # Formatting the hetero value
                het = None
                try:
                    het = "{:.4f}".format(float(row[header["HETERO"]]))
                except:
                    het = "N/A"

                hetero[(famid, indid)] = het

    # Reading the number of no call on Y
    nb_no_call = {}
    if os.path.isfile(script_prefix + ".chr24_recodeA.raw.noCall"):
        with open(script_prefix + ".chr24_recodeA.raw.noCall", "r") as i_file:
            header = {
                name: i for i, name in
                enumerate(createRowFromPlinkSpacedOutput(i_file.readline()))
            }
            for required_col in ("PED", "ID", "nbGeno", "nbNoCall"):
                if required_col not in header:
                    msg = "{}: no column named {}".format(
                        script_prefix + ".chr24_recodeA.raw.noCall",
                        required_col,
                    )
                    raise ProgramError(msg)

            # Reading the data
            for line in i_file:
                row = line.rstrip("\r\n").split("\t")
                famid = row[header["PED"]]
                indid = row[header["ID"]]

                # Getting the statistics
                nb_geno = row[header["nbGeno"]]
                nb_nocall = row[header["nbNoCall"]]

                percent = None
                try:
                    percent = "{:.4f}".format(
                        float(nb_nocall) / float(nb_geno),
                    )
                except:
                    percent = "N/A"
                nb_no_call[(famid, indid)] = percent

    # Reading the problem file to gather statistics. Note that dataset without
    # problem will only have the header line (and no data)
    nb_problems = 0
    table = []
    nb_no_genetic = 0
    nb_discordant = 0
    with open(script_prefix + ".list_problem_sex", "r") as i_file:
        # Reading the header
        header = i_file.readline().rstrip("\r\n").split("\t")
        table.append(header)
        header = {name: i for i, name in enumerate(header)}
        for required_col in ("FID", "IID", "SNPSEX"):
            if required_col not in header:
                msg = "{}: no column named {}".format(
                    script_prefix + ".list_problem_sex",
                    required_col,
                )
                raise ProgramError(msg)

        # Adding the missing column name
        table[-1].append("HET")
        table[-1].append(r"\%NOCALL")

        # Reading the rest of the data
        for line in i_file:
            nb_problems += 1

            # Creating the row
            row = line.rstrip("\r\n").split("\t")

            # Counting
            if row[header["SNPSEX"]] == "0":
                nb_no_genetic += 1
            else:
                nb_discordant += 1

            table.append([
                latex_template.sanitize_tex(row[header[name]])
                for name in ("FID", "IID", "PEDSEX", "SNPSEX", "STATUS", "F")
            ])
            table[-1].append(
                hetero.get((row[header["FID"]], row[header["IID"]]), "N/A"),
            )
            table[-1].append(
                nb_no_call.get((row[header["FID"]], row[header["IID"]]), "N/A")
            )

    # Getting the value for the maleF option
    male_f = sex_check.parser.get_default("maleF")
    if "--maleF" in options:
        male_f = options[options.index("--maleF") + 1]

    # Getting the value for the femaleF option
    female_f = sex_check.parser.get_default("femaleF")
    if "--femaleF" in options:
        female_f = options[options.index("--femaleF") + 1]

    # We write a LaTeX summary
    latex_file = os.path.join(script_prefix + ".summary.tex")
    graphics_paths = set()
    try:
        with open(latex_file, "w") as o_file:
            print >>o_file, latex_template.subsection(sex_check.pretty_name)
            text = (
                "Using $F$ thresholds of {male_f} and {female_f} for males "
                "and females respectively, {nb_problems:,d} sample{plural} "
                "had gender problem according to Plink.".format(
                    male_f=male_f,
                    female_f=female_f,
                    nb_problems=nb_problems,
                    plural="s" if nb_problems > 1 else "",
                )
            )
            print >>o_file, latex_template.wrap_lines(text)

            # The float template
            float_template = latex_template.jinja2_env.get_template(
                "float_template.tex",
            )

            if nb_problems > 0:
                # The label and text for the table
                table_label = re.sub(
                    r"[/\\]",
                    "_",
                    script_prefix,
                ) + "_problems"
                text = (
                    r"Table~\ref{" + table_label + "} summarizes the gender "
                    "problems encountered during the analysis."
                )
                print >>o_file, latex_template.wrap_lines(text)

                # Getting the template
                longtable_template = latex_template.jinja2_env.get_template(
                    "longtable_template.tex",
                )

                # Rendering
                print >>o_file, longtable_template.render(
                    table_caption="Summarization of the gender problems "
                                  "encountered during Plink's analysis. "
                                  "HET is the heterozygosity rate on the X "
                                  r"chromosome. \%NOCALL is the percentage of "
                                  "no calls on the Y chromosome.",
                    table_label=table_label,
                    nb_col=len(table[1]),
                    col_alignments="llrrlrrrr",
                    text_size="scriptsize",
                    header_data=zip(table[0], [1 for i in table[0]]),
                    tabular_data=sorted(table[1:], key=lambda item: item[1]),
                )

            # Getting the templates
            graphic_template = latex_template.jinja2_env.get_template(
                "graphics_template.tex",
            )

            # If there is a figure, we add it here
            if os.path.isfile(script_prefix + ".png"):
                # Adding the figure
                figure_label = re.sub(r"[/\\]", "_", script_prefix)
                text = (
                    r"Figure~\ref{" + figure_label + r"} shows the $\bar{y}$ "
                    r"intensities versus the $\bar{x}$ intensities for each "
                    "samples. Problematic samples are shown using triangles."
                )
                print >>o_file, latex_template.wrap_lines(text)

                # Getting the paths
                graphics_path, path = os.path.split(script_prefix + ".png")
                graphics_path = os.path.relpath(graphics_path, base_dir)

                print >>o_file, float_template.render(
                    float_type="figure",
                    float_placement="H",
                    float_caption="Gender check using Plink. Mean $x$ and $y$ "
                                  "intensities are shown for each sample. "
                                  "Males are shown in blue, and females in "
                                  "red. Triangles show problematic samples "
                                  "(green for males, mauve for females). "
                                  "Unknown gender are shown in gray.",
                    float_label=figure_label,
                    float_content=graphic_template.render(
                        width=r"0.8\textwidth",
                        path=latex_template.sanitize_fig_name(path),
                    ),
                )
                # Adding the path where the graphic is
                graphics_paths.add(graphics_path)

            # If there is a 'sexcheck.LRR_BAF' directory, then there are LRR
            # and BAF plots.
            if os.path.isdir(script_prefix + ".LRR_BAF"):
                figures = glob(
                    os.path.join(script_prefix + ".LRR_BAF", "*.png"),
                )

                if len(figures) > 0:
                    # Getting the sample IDs
                    sample_ids = [
                        re.search(
                            "^baf_lrr_(\S+)_lrr_baf.png$",
                            os.path.basename(figure),
                        ) for figure in figures
                    ]
                    sample_ids = [
                        "unknown sample" if not sample else sample.group(1)
                        for sample in sample_ids
                    ]

                    # Sorting according to sample IDs
                    sorted_indexes = sorted(range(len(figures)),
                                            key=figures.__getitem__)
                    figures = [figures[i] for i in sorted_indexes]
                    sample_ids = [sample_ids[i] for i in sorted_indexes]

                    # Getting the labels
                    labels = [
                        re.sub(
                            r"[/\\]",
                            "_",
                            script_prefix + "_baf_lrr_" +
                            os.path.splitext(sample)[0],
                        ) for sample in sample_ids
                    ]

                    fig_1 = labels[0]
                    fig_2 = ""
                    if len(figures) > 1:
                        fig_2 = labels[-1]
                    text = (
                        "Figure" + ("s" if len(figures) > 1 else "") +
                        r"~\ref{" + fig_1 + "} " +
                        (r"to \ref{" + fig_2 + "} " if fig_2 else "") +
                        "show" + (" " if len(figures) > 1 else "s ") + "the "
                        "log R ratio and the B allele frequency versus the "
                        "position on chromosome X and Y for the problematic "
                        "sample{}.".format("s" if len(figures) > 1 else "")
                    )
                    print >>o_file, latex_template.wrap_lines(text)

                    zipped = zip(figures, sample_ids, labels)
                    for figure, sample_id, label in zipped:
                        sample_id = latex_template.sanitize_tex(sample_id)

                        # Getting the paths
                        graphics_path, path = os.path.split(figure)
                        graphics_path = os.path.relpath(graphics_path,
                                                        base_dir)

                        caption = (
                            "Plots showing the log R ratio and the B allele "
                            "frequency for chromosome X and Y (on the left "
                            "and right, respectively) for sample "
                            "{}.".format(sample_id)
                        )
                        print >>o_file, float_template.render(
                            float_type="figure",
                            float_placement="H",
                            float_caption=caption,
                            float_label=label,
                            float_content=graphic_template.render(
                                width=r"\textwidth",
                                path=latex_template.sanitize_fig_name(path),
                            ),
                        )
                # Adding the path where the graphic is
                graphics_paths.add(graphics_path)

    except IOError:
        msg = "{}: cannot write LaTeX summary".format(latex_file)
        raise ProgramError(msg)

    # Writing the summary results
    with open(os.path.join(base_dir, "results_summary.txt"), "a") as o_file:
        print >>o_file, "# {}".format(script_prefix)
        print >>o_file, "Number of samples with gender problem"
        print >>o_file, "  - no genetic gender\t{:,d}".format(nb_no_genetic)
        print >>o_file, "  - discordant gender\t{:,d}".format(nb_discordant)
        print >>o_file, "---"

    # We know this step does not produce a new data set, so we return the
    # original one
    return _StepResult(
        next_file=in_prefix,
        next_file_type=required_type,
        latex_summary=latex_file,
        description=sex_check.desc,
        long_description=sex_check.long_desc,
        graph_path=graphics_paths,
    )