# Buggy code
def __init__(self):
    # Initialise the parent object
    super(MultiqcModule, self).__init__(
        name="bcl2fastq",
        anchor="bcl2fastq",
        href="https://support.illumina.com/sequencing/sequencing_software/bcl2fastq-conversion-software.html",
        info="can be used to both demultiplex data and convert BCL files to FASTQ file formats for downstream analysis.",
    )

    # Gather data from all json files
    self.bcl2fastq_data = dict()
    for myfile in self.find_log_files("bcl2fastq"):
        self.parse_file_as_json(myfile)

    # Collect counts by lane and sample (+source_files)
    self.bcl2fastq_bylane = dict()
    self.bcl2fastq_bysample = dict()
    self.source_files = dict()
    self.split_data_by_lane_and_sample()

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

    # Return with Warning if no files are found
    if len(self.bcl2fastq_bylane) == 0 and len(self.bcl2fastq_bysample) == 0:
        raise UserWarning

    # Print source files
    for s in self.source_files.keys():
        self.add_data_source(
            s_name=s,
            source=",".join(list(set(self.source_files[s]))),
            module="bcl2fastq",
            section="bcl2fastq-bysample",
        )

    # Add sample counts to general stats table
    self.add_general_stats()
    self.write_data_file(
        {str(k): self.bcl2fastq_bylane[k] for k in self.bcl2fastq_bylane.keys()},
        "multiqc_bcl2fastq_bylane",
    )
    self.write_data_file(self.bcl2fastq_bysample, "multiqc_bcl2fastq_bysample")

    # Add section for summary stats per flow cell
    self.add_section(
        name="Lane Statistics",
        anchor="bcl2fastq-lanestats",
        description="Statistics about each lane for each flowcell",
        plot=self.lane_stats_table(),
    )

    # Add section for counts by lane
    cats = OrderedDict()
    cats["perfect"] = {"name": "Perfect Index Reads"}
    cats["imperfect"] = {"name": "Mismatched Index Reads"}
    cats["undetermined"] = {"name": "Undetermined Reads"}
    self.add_section(
        name="Clusters by lane",
        anchor="bcl2fastq-bylane",
        description="Number of reads per lane (with number of perfect index reads).",
        helptext="""Perfect index reads are those that do not have a single mismatch.
                All samples of a lane are combined. Undetermined reads are treated as a third category.
                To avoid conflicts the run ID is prepended.""",
        plot=bargraph.plot(
            self.get_bar_data_from_counts(self.bcl2fastq_bylane),
            cats,
            {"id": "bcl2fastq_lane_counts", "title": "bcl2tfastq: Clusters by lane"},
        ),
    )

    # Add section for counts by sample
    self.add_section(
        name="Clusters by sample",
        anchor="bcl2fastq-bysample",
        description="Number of reads per sample (with number of perfect index reads)",
        helptext="""Perfect index reads are those that do not have a single mismatch.
                All samples are aggregated across lanes combinned. Undetermined reads are ignored.
                Undetermined reads are treated as a separate sample.
                To avoid conflicts the runId is prepended.""",
        plot=bargraph.plot(
            self.get_bar_data_from_counts(self.bcl2fastq_bysample),
            cats,
            {
                "id": "bcl2fastq_sample_counts",
                "title": "bcl2tfastq: Clusters by sample",
            },
        ),
    )


# Traceback (KeyError)
[ERROR  ]         multiqc : Oops! The 'bcl2fastq' MultiQC module broke...
Please copy the following traceback and report it at https://github.com/ewels/MultiQC/issues
(if possible, include a log file that triggers the error)
============================================================
Module bcl2fastq raised an exception: Traceback (most recent call last):
File "/camp/stp/babs/working/software/binaries/Python-2.7.12-foss-2016b_packages/multiqc-1.2-2016b-Python-2.7.12/lib/python2.7/site-packages/multiqc-1.2-py2.7.egg/EGG-INFO/scripts/multiqc", line 411, in multiqc
output = mod()
File "/camp/stp/babs/working/software/binaries/Python-2.7.12-foss-2016b_packages/multiqc-1.2-2016b-Python-2.7.12/lib/python2.7/site-packages/multiqc-1.2-py2.7.egg/multiqc/modules/bcl2fastq/bcl2fastq.py", line 21, in __init__
self.parse_file_as_json(myfile)
File "/camp/stp/babs/working/software/binaries/Python-2.7.12-foss-2016b_packages/multiqc-1.2-2016b-Python-2.7.12/lib/python2.7/site-packages/multiqc-1.2-py2.7.egg/multiqc/modules/bcl2fastq/bcl2fastq.py", line 120, in parse_file_as_json
for indexMetric in demuxResult["IndexMetrics"]:
KeyError: 'IndexMetrics'
============================================================

# Fixed code
def __init__(self):
    # Initialise the parent object
    super(MultiqcModule, self).__init__(
        name="bcl2fastq",
        anchor="bcl2fastq",
        href="https://support.illumina.com/sequencing/sequencing_software/bcl2fastq-conversion-software.html",
        info="can be used to both demultiplex data and convert BCL files to FASTQ file formats for downstream analysis.",
    )

    # Gather data from all json files
    self.bcl2fastq_data = dict()
    for myfile in self.find_log_files("bcl2fastq"):
        self.parse_file_as_json(myfile)

    # Collect counts by lane and sample (+source_files)
    self.bcl2fastq_bylane = dict()
    self.bcl2fastq_bysample = dict()
    self.source_files = dict()
    self.split_data_by_lane_and_sample()

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

    # Return with Warning if no files are found
    if len(self.bcl2fastq_bylane) == 0 and len(self.bcl2fastq_bysample) == 0:
        raise UserWarning

    # Print source files
    for s in self.source_files.keys():
        self.add_data_source(
            s_name=s,
            source=",".join(list(set(self.source_files[s]))),
            module="bcl2fastq",
            section="bcl2fastq-bysample",
        )

    # Add sample counts to general stats table
    self.add_general_stats()
    self.write_data_file(
        {str(k): self.bcl2fastq_bylane[k] for k in self.bcl2fastq_bylane.keys()},
        "multiqc_bcl2fastq_bylane",
    )
    self.write_data_file(self.bcl2fastq_bysample, "multiqc_bcl2fastq_bysample")

    # Add section for summary stats per flow cell
    self.add_section(
        name="Lane Statistics",
        anchor="bcl2fastq-lanestats",
        description="Statistics about each lane for each flowcell",
        plot=self.lane_stats_table(),
    )

    # Add section for counts by lane
    cats = OrderedDict()
    cats["perfect"] = {"name": "Perfect Index Reads"}
    cats["imperfect"] = {"name": "Mismatched Index Reads"}
    cats["undetermined"] = {"name": "Undetermined Reads"}
    self.add_section(
        name="Clusters by lane",
        anchor="bcl2fastq-bylane",
        description="Number of reads per lane (with number of perfect index reads).",
        helptext="""Perfect index reads are those that do not have a single mismatch.
                All samples of a lane are combined. Undetermined reads are treated as a third category.
                To avoid conflicts the run ID is prepended.""",
        plot=bargraph.plot(
            self.get_bar_data_from_counts(self.bcl2fastq_bylane),
            cats,
            {
                "id": "bcl2fastq_lane_counts",
                "title": "bcl2fastq: Clusters by lane",
                "hide_zero_cats": False,
            },
        ),
    )

    # Add section for counts by sample
    self.add_section(
        name="Clusters by sample",
        anchor="bcl2fastq-bysample",
        description="Number of reads per sample (with number of perfect index reads)",
        helptext="""Perfect index reads are those that do not have a single mismatch.
                All samples are aggregated across lanes combinned. Undetermined reads are ignored.
                Undetermined reads are treated as a separate sample.
                To avoid conflicts the runId is prepended.""",
        plot=bargraph.plot(
            self.get_bar_data_from_counts(self.bcl2fastq_bysample),
            cats,
            {
                "id": "bcl2fastq_sample_counts",
                "title": "bcl2fastq: Clusters by sample",
                "hide_zero_cats": False,
            },
        ),
    )