# Buggy code
def __init__(self):
    # Initialise the parent object
    super(MultiqcModule, self).__init__(
        name="Peddy",
        anchor="peddy",
        href="https://github.com/brentp/peddy",
        info="calculates genotype :: pedigree correspondence checks, ancestry checks and sex checks using VCF files.",
    )

    # Find and load any Peddy reports
    self.peddy_data = dict()
    self.peddy_length_counts = dict()
    self.peddy_length_exp = dict()
    self.peddy_length_obsexp = dict()

    # parse peddy summary file
    for f in self.find_log_files("peddy/summary_table"):
        parsed_data = self.parse_peddy_summary(f)
        if parsed_data is not None:
            for s_name in parsed_data:
                s_name = self.clean_s_name(s_name, f["root"])
                try:
                    self.peddy_data[s_name].update(parsed_data[s_name])
                except KeyError:
                    self.peddy_data[s_name] = parsed_data[s_name]
    # parse peddy CSV files
    for pattern in ["het_check", "ped_check", "sex_check"]:
        sp_key = "peddy/{}".format(pattern)
        for f in self.find_log_files(sp_key):
            # some columns have the same name in het_check and sex_check (median_depth)
            # pass pattern to parse_peddy_csv so the column names can include pattern to
            # avoid being overwritten
            parsed_data = self.parse_peddy_csv(f, pattern)
            if parsed_data is not None:
                for s_name in parsed_data:
                    s_name = self.clean_s_name(s_name, f["root"])
                    try:
                        self.peddy_data[s_name].update(parsed_data[s_name])
                    except KeyError:
                        self.peddy_data[s_name] = parsed_data[s_name]
    # parse background PCA JSON file, this is identitical for all peddy runs,
    # so just parse the first one we find
    for f in self.find_log_files("peddy/background_pca"):
        background = json.loads(f["f"])
        PC1 = [x["PC1"] for x in background]
        PC2 = [x["PC2"] for x in background]
        ancestry = [x["ancestry"] for x in background]
        self.peddy_data["background_pca"] = {
            "PC1": PC1,
            "PC2": PC2,
            "ancestry": ancestry,
        }
        break

    # Filter to strip out ignored sample names
    self.peddy_data = self.ignore_samples(self.peddy_data)

    if len(self.peddy_data) == 0:
        raise UserWarning

    log.info("Found {} reports".format(len(self.peddy_data)))

    # Write parsed report data to a file
    self.write_data_file(self.peddy_data, "multiqc_peddy")

    # Basic Stats Table
    self.peddy_general_stats_table()

    # PCA plot
    self.peddy_pca_plot()

    # Relatedness plot
    self.peddy_relatedness_plot()

    # hetcheck plot
    self.peddy_het_check_plot()

    self.peddy_sex_check_plot()


# Traceback (KeyError)
[INFO   ]         multiqc : This is MultiQC v1.7
[INFO   ]         multiqc : Template    : default
[INFO   ]         multiqc : Searching '/home/ubuntu/naumenko/sample_b2/work/qc/multiqc/report/metrics/target_info.yaml'
[INFO   ]         multiqc : Searching '/home/ubuntu/naumenko/sample_b2/work/qc/ts_bcbio/contamination/ts_bcbio-verifybamid.failed'
[INFO   ]         multiqc : Searching '/home/ubuntu/naumenko/sample_b2/work/qc/ts_bcbio/fastqc/Per_base_N_content.tsv'
[INFO   ]         multiqc : Searching '/home/ubuntu/naumenko/sample_b2/work/qc/ts_bcbio/fastqc/Per_base_sequence_content.tsv'
[INFO   ]         multiqc : Searching '/home/ubuntu/naumenko/sample_b2/work/qc/ts_bcbio/fastqc/Per_base_sequence_quality.tsv'
[INFO   ]         multiqc : Searching '/home/ubuntu/naumenko/sample_b2/work/qc/ts_bcbio/fastqc/Per_sequence_GC_content.tsv'
[INFO   ]         multiqc : Searching '/home/ubuntu/naumenko/sample_b2/work/qc/ts_bcbio/fastqc/Per_sequence_quality_scores.tsv'
[INFO   ]         multiqc : Searching '/home/ubuntu/naumenko/sample_b2/work/qc/ts_bcbio/fastqc/Sequence_Duplication_Levels.tsv'
[INFO   ]         multiqc : Searching '/home/ubuntu/naumenko/sample_b2/work/qc/ts_bcbio/fastqc/Sequence_Length_Distribution.tsv'
[INFO   ]         multiqc : Searching '/home/ubuntu/naumenko/sample_b2/work/qc/ts_bcbio/fastqc/fastqc_data.txt'
[INFO   ]         multiqc : Searching '/home/ubuntu/naumenko/sample_b2/work/qc/ts_bcbio/fastqc/fastqc_report.html'
[INFO   ]         multiqc : Searching '/home/ubuntu/naumenko/sample_b2/work/qc/ts_bcbio/fastqc/ts_bcbio.zip'
[INFO   ]         multiqc : Searching '/home/ubuntu/naumenko/sample_b2/work/qc/ts_bcbio/peddy/ts_bcbio.background_pca.json'
[INFO   ]         multiqc : Searching '/home/ubuntu/naumenko/sample_b2/work/qc/ts_bcbio/peddy/ts_bcbio.het_check.csv'
[INFO   ]         multiqc : Searching '/home/ubuntu/naumenko/sample_b2/work/qc/ts_bcbio/peddy/ts_bcbio.html'
[INFO   ]         multiqc : Searching '/home/ubuntu/naumenko/sample_b2/work/qc/ts_bcbio/peddy/ts_bcbio.ped_check.csv'
[INFO   ]         multiqc : Searching '/home/ubuntu/naumenko/sample_b2/work/qc/ts_bcbio/peddy/ts_bcbio.ped_check.rel-difference.csv'
[INFO   ]         multiqc : Searching '/home/ubuntu/naumenko/sample_b2/work/qc/ts_bcbio/peddy/ts_bcbio.peddy.ped'
[INFO   ]         multiqc : Searching '/home/ubuntu/naumenko/sample_b2/work/qc/ts_bcbio/peddy/ts_bcbio.sex_check.csv'
[INFO   ]         multiqc : Searching '/home/ubuntu/naumenko/sample_b2/work/qc/ts_bcbio/samtools/ts_bcbio-idxstats.txt'
[INFO   ]         multiqc : Searching '/home/ubuntu/naumenko/sample_b2/work/qc/ts_bcbio/samtools/ts_bcbio.txt'
[INFO   ]         multiqc : Searching '/home/ubuntu/naumenko/sample_b2/work/qc/ts_bcbio/variants/ts_bcbio.txt'
[INFO   ]         multiqc : Searching '/home/ubuntu/naumenko/sample_b2/work/qc/ts_bcbio/variants/ts_bcbio_bcftools_stats.txt'
[INFO   ]         multiqc : Searching '/home/ubuntu/naumenko/sample_b2/work/qc/ts_bcbio/variants/ts_bcbio_bcftools_stats_germline.txt'
[INFO   ]         multiqc : Searching '/home/ubuntu/naumenko/sample_b2/work/qc/ts_bcbio/viral/ts_bcbio-gdc-viral-completeness.txt'
[INFO   ]         multiqc : Searching '/home/ubuntu/naumenko/sample_b2/work/qc/multiqc/report/metrics/ts_bcbio_bcbio.txt'
[INFO   ]           bcbio : Found 1 reports
/bcbio/anaconda/lib/python3.6/site-packages/multiqc_bcbio/bcbio.py:77: YAMLLoadWarning: calling yaml.load() without Loader=... is deprecated, as the default Loader is unsafe. Please read https://msg.pyyaml.org/load for full details.
add_project_info(yaml.load(target_infos[0]['f']))
[INFO   ]        samtools : Found 1 idxstats reports
[ERROR  ]         multiqc : Oops! The 'peddy' MultiQC module broke...
Please copy the following traceback and report it at https://github.com/ewels/MultiQC/issues
If possible, please include a log file that triggers the error - the last file found was:
/home/ubuntu/naumenko/sample_b2/work/qc/ts_bcbio/peddy/ts_bcbio.sex_check.csv
============================================================
Module peddy raised an exception: Traceback (most recent call last):
File "/bcbio/anaconda/lib/python3.6/site-packages/multiqc/modules/peddy/peddy.py", line 58, in __init__
self.peddy_data[s_name].update(parsed_data[s_name])
KeyError: 'ts'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/bcbio/tools/bin/multiqc", line 440, in multiqc
output = mod()
File "/bcbio/anaconda/lib/python3.6/site-packages/multiqc/modules/peddy/peddy.py", line 60, in __init__
self.peddy_data[s_name] = parsed_data[s_name]
KeyError: 'ts'
============================================================
[INFO   ]        bcftools : Found 1 stats reports
[INFO   ]        bcftools : Found 1 stats reports
[INFO   ]          fastqc : Found 1 reports
[INFO   ]         multiqc : Compressing plot data
[INFO   ]         multiqc : Report      : ../../bcbiotx/tmp1n5rgkh7/multiqc_report.html
[INFO   ]         multiqc : Data        : ../../bcbiotx/tmp1n5rgkh7/multiqc_data
[INFO   ]         multiqc : MultiQC complete
' returned non-zero exit status 1.

# Fixed code
def __init__(self):
    # Initialise the parent object
    super(MultiqcModule, self).__init__(
        name="Peddy",
        anchor="peddy",
        href="https://github.com/brentp/peddy",
        info="calculates genotype :: pedigree correspondence checks, ancestry checks and sex checks using VCF files.",
    )

    # Find and load any Peddy reports
    self.peddy_data = dict()
    self.peddy_length_counts = dict()
    self.peddy_length_exp = dict()
    self.peddy_length_obsexp = dict()

    # parse peddy summary file
    for f in self.find_log_files("peddy/summary_table"):
        parsed_data = self.parse_peddy_summary(f)
        if parsed_data is not None:
            for s_name in parsed_data:
                s_name = self.clean_s_name(s_name, f["root"])
                try:
                    self.peddy_data[s_name].update(parsed_data[s_name])
                except KeyError:
                    self.peddy_data[s_name] = parsed_data[s_name]

    # parse peddy CSV files
    for pattern in ["het_check", "ped_check", "sex_check"]:
        sp_key = "peddy/{}".format(pattern)
        for f in self.find_log_files(sp_key):
            # some columns have the same name in het_check and sex_check (median_depth)
            # pass pattern to parse_peddy_csv so the column names can include pattern to
            # avoid being overwritten
            parsed_data = self.parse_peddy_csv(f, pattern)
            if parsed_data is not None:
                for s_name in parsed_data:
                    try:
                        self.peddy_data[s_name].update(parsed_data[s_name])
                    except KeyError:
                        self.peddy_data[s_name] = parsed_data[s_name]

    # parse background PCA JSON file, this is identitical for all peddy runs,
    # so just parse the first one we find
    for f in self.find_log_files("peddy/background_pca"):
        background = json.loads(f["f"])
        PC1 = [x["PC1"] for x in background]
        PC2 = [x["PC2"] for x in background]
        ancestry = [x["ancestry"] for x in background]
        self.peddy_data["background_pca"] = {
            "PC1": PC1,
            "PC2": PC2,
            "ancestry": ancestry,
        }
        break

    # Filter to strip out ignored sample names
    self.peddy_data = self.ignore_samples(self.peddy_data)

    if len(self.peddy_data) == 0:
        raise UserWarning

    log.info("Found {} reports".format(len(self.peddy_data)))

    # Write parsed report data to a file
    self.write_data_file(self.peddy_data, "multiqc_peddy")

    # Basic Stats Table
    self.peddy_general_stats_table()

    # PCA plot
    self.peddy_pca_plot()

    # Relatedness plot
    self.peddy_relatedness_plot()

    # hetcheck plot
    self.peddy_het_check_plot()

    self.peddy_sex_check_plot()