Runs step7 (plate bias).

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

def run_plate_bias(in_prefix, in_type, out_prefix, base_dir, options):
    """Runs step7 (plate bias).

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

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

    # The name of the summary file
    filename = script_prefix + ".significant_SNPs.summary"
    if not os.path.isfile(filename):
        raise ProgramError("{}: no such file".format(filename))

    # Getting the number of each plate
    plate_counter = None
    with open(filename, "r") as i_file:
        header = {
            name: i for i, name in
            enumerate(i_file.readline().rstrip("\r\n").split("\t"))
        }
        if "plate" not in header:
            msg = "{}: missing column plate".format(filename)
            raise ProgramError(msg)

        # Counting the number of markers for each plate
        plate_counter = Counter(
            line.rstrip("\r\n").split("\t")[header["plate"]] for line in i_file
        )

    # Creating the table
    table = [["plate name", "number of markers"]]
    for plate_name, number in plate_counter.most_common():
        table.append([
            latex_template.sanitize_tex(plate_name),
            "{:,d}".format(number),
        ])

    # The number of unique markers
    filename = script_prefix + ".significant_SNPs.txt"
    nb_markers = None
    with open(filename, "r") as i_file:
        nb_markers = len({line.rstrip("\r\n") for line in i_file})

    # Getting the p value threshold
    p_threshold = str(plate_bias.parser.get_default("pfilter"))
    if "--pfilter" in options:
        p_threshold = str(options[options.index("--pfilter") + 1])

    # We write a LaTeX summary
    latex_file = os.path.join(script_prefix + ".summary.tex")
    try:
        with open(latex_file, "w") as o_file:
            print >>o_file, latex_template.subsection(plate_bias.pretty_name)
            text = (
                "After performing the plate bias analysis using Plink, a "
                "total of {:,d} unique marker{} had a significant result "
                "({} a value less than {}).".format(
                    nb_markers,
                    "s" if nb_markers > 1 else "",
                    r"\textit{i.e.}",
                    latex_template.format_numbers(p_threshold),
                )
            )
            print >>o_file, latex_template.wrap_lines(text)

            if nb_markers > 0:
                table_label = re.sub(
                    r"[/\\]",
                    "_",
                    script_prefix,
                ) + "_plate_bias"
                text = (
                    r"Table~\ref{" + table_label + "} summarizes the plate "
                    "bias results."
                )
                print >>o_file, latex_template.wrap_lines(text)

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

                # The table caption
                table_caption = (
                    "Summary of the plate bias analysis performed by Plink. "
                    "For each plate, the number of significant marker{} is "
                    "shown (threshold of {}). The plates are sorted according "
                    "to the total number of significant results.".format(
                        "s" if nb_markers > 1 else "",
                        latex_template.format_numbers(p_threshold),
                    )
                )
                print >>o_file, longtable_template.render(
                    table_caption=table_caption,
                    table_label=table_label,
                    nb_col=len(table[1]),
                    col_alignments="lr",
                    text_size="normalsize",
                    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 with plate bias (p<{})\t"
                         "{:,d}".format(p_threshold, nb_markers))
        print >>o_file, "---"

    # 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=plate_bias.desc,
        long_description=plate_bias.long_desc,
        graph_path=None,
    )