Runs step9 (find related samples).

    :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.RelatedSamples.find_related_samples` 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.RelatedSamples.find_related_samples` module
        doesn't return usable output files. Hence, this function returns the
        input file prefix and its type.

def run_find_related_samples(in_prefix, in_type, out_prefix, base_dir,
                             options):
    """Runs step9 (find related samples).

    :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.RelatedSamples.find_related_samples` 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.RelatedSamples.find_related_samples` 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 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, "ibs")
    options += ["--{}".format(required_type), in_prefix,
                "--out", script_prefix]

    # The IBS2 ratio
    ibs2_ratio = find_related_samples._ibs2_ratio_default
    if "--ibs2-ratio" in options:
        ibs2_ratio = options[options.index("--ibs2-ratio") + 1]

    # The indep pairwiase
    r2_value = find_related_samples._indep_pairwise_r2_default
    if "--indep-pairwise" in options:
        r2_value = options[options.index("--indep-pairwise") + 3]

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

    # Reading the file containing all samples that are related
    #   - ibs.related_individuals
    related_samples = set()
    with open(script_prefix + ".related_individuals", "r") as i_file:
        header = {
            name: i for i, name in
            enumerate(createRowFromPlinkSpacedOutput(i_file.readline()))
        }
        for required_col in ["FID1", "IID1", "FID2", "IID2"]:
            if required_col not in header:
                msg = "{}: missing column {}".format(
                    script_prefix + ".related_individuals",
                    required_col,
                )
                raise ProgramError(msg)

        # Reading the rest of the data
        for line in i_file:
            row = createRowFromPlinkSpacedOutput(line)
            related_samples.add((row[header["FID1"]], row[header["IID1"]]))
            related_samples.add((row[header["FID2"]], row[header["IID2"]]))

    # Reading file containing samples that should be discarded
    #   - ibs.discarded_related_individuals
    discarded_samples = None
    with open(script_prefix + ".discarded_related_individuals", "r") as i_file:
        discarded_samples = {
            tuple(i.rstrip("\r\n").split("\t")) for i in i_file
        }

    # Counting the number of markers used for computing IBS values
    nb_markers_ibs = 0
    with open(script_prefix + ".pruned_data.bim", "r") as i_file:
        for line in i_file:
            nb_markers_ibs += 1

    # Reading the merged related individuals file
    table = []
    with open(script_prefix + ".merged_related_individuals", "r") as i_file:
        for line in i_file:
            table.append([
                latex_template.sanitize_tex(item)
                for item in line.rstrip("\r\n").split("\t")
            ])

    # 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(
                find_related_samples.pretty_name,
            )
            text = (
                "According to Plink relatedness analysis (using {:,d} "
                "marker{}), {:,d} unique sample{} {} related to at least one "
                "other sample. A total of {:,d} sample{} {} randomly selected "
                "for downstream exclusion from the dataset.".format(
                    nb_markers_ibs,
                    "s" if nb_markers_ibs > 1 else "",
                    len(related_samples),
                    "s" if len(related_samples) > 1 else "",
                    "were" if len(related_samples) > 1 else "was",
                    len(discarded_samples),
                    "s" if len(discarded_samples) > 1 else "",
                    "were" if len(discarded_samples) > 1 else "was",
                )
            )
            print >>o_file, latex_template.wrap_lines(text)

            # Adding the first figure (if present)
            fig_1 = script_prefix + ".related_individuals_z1.png"
            fig_1_label = re.sub(r"[/\\]", "_", script_prefix) + "_z1"
            if os.path.isfile(fig_1):
                text = (
                    r"Figure~\ref{" + fig_1_label + "} shows $Z_1$ versus "
                    r"$IBS2_{ratio}^\ast$ for all related samples found by "
                    r"Plink."
                )
                print >>o_file, latex_template.wrap_lines(text)

            # Adding the second figure (if present)
            fig_2 = script_prefix + ".related_individuals_z2.png"
            fig_2_label = re.sub(r"[/\\]", "_", script_prefix) + "_z2"
            if os.path.isfile(fig_2):
                text = (
                    r"Figure~\ref{" + fig_2_label + "} shows $Z_2$ versus "
                    r"$IBS2_{ratio}^\ast$ for all related samples found by "
                    r"Plink."
                )
                print >>o_file, latex_template.wrap_lines(text)

            if len(table) > 1:
                # There is data, so we add
                table_label = re.sub(r"[/\\]", "_", script_prefix) + "_related"
                text = (
                    r"Table~\ref{" + table_label + "} lists the related "
                    "sample pairs with estimated relationship."
                )
                print >>o_file, latex_template.wrap_lines(text)

            # Getting the required template
            float_template = latex_template.jinja2_env.get_template(
                "float_template.tex",
            )
            graphic_template = latex_template.jinja2_env.get_template(
                "graphics_template.tex",
            )

            figures = (fig_1, fig_2)
            labels = (fig_1_label, fig_2_label)
            graph_types = ("$Z_1$", "$Z_2$")
            for fig, label, graph_type in zip(figures, labels, graph_types):
                if os.path.isfile(fig):
                    # Getting the paths
                    graphics_path, path = os.path.split(fig)
                    graphics_path = os.path.relpath(graphics_path, base_dir)

                    # Printing
                    caption = (
                        graph_type + r" versus $IBS2_{ratio}^\ast$ for all "
                        "related samples found by Plink in the IBS analysis."
                    )
                    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"0.8\textwidth",
                            path=latex_template.sanitize_fig_name(path),
                        ),
                    )
                    # Adding the path where the graphic is
                    graphics_paths.add(graphics_path)

            # Adding the table
            if len(table) > 1:
                # Getting the template
                longtable_template = latex_template.jinja2_env.get_template(
                    "longtable_template.tex",
                )

                # The table caption
                table_caption = (
                    "List of all related samples with estimated relationship. "
                    "Sample pairs are grouped according to their estimated "
                    "family (the index column)."
                )
                print >>o_file, longtable_template.render(
                    table_caption=table_caption,
                    table_label=table_label,
                    nb_col=len(table[1]),
                    col_alignments="rlllll",
                    text_size="scriptsize",
                    header_data=zip(table[0], [1 for i in table[0]]),
                    tabular_data=table[1:],
                )

    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 markers used for IBS analysis\t"
                         "{:,d}".format(nb_markers_ibs))
        print >>o_file, ("Number of unique related samples\t"
                         "{:,d}".format(len(related_samples)))
        print >>o_file, "---"

    # The long description
    long_description = find_related_samples.long_desc.format(
        ratio="{ratio}",
        ratio_value=ibs2_ratio,
        r_squared=r2_value,
    )

    # We know this step doesn't produce an new data set, so we return the old
    # prefix and the old in_type
    return _StepResult(
        next_file=in_prefix,
        next_file_type=required_type,
        latex_summary=latex_file,
        description=find_related_samples.desc,
        long_description=long_description,
        graph_path=graphics_paths,
    )