Take the parsed stats from the leeHom report and add it to the
        basic stats table at the top of the report
542132
def leehom_general_stats_table(self):
        

        headers = {}
        headers['merged_trimming'] = {
            'title': '{} Merged (Trimming)'.format(config.read_count_prefix),
            'description': 'Merged clusters from trimming ({})'.format(config.read_count_desc),
            'min': 0,
            'scale': 'PuRd',
            'modify': lambda x: x * config.read_count_multiplier,
            'shared_key': 'read_count'
        }
        headers['merged_overlap'] = {
            'title': '{} Merged (Overlap)'.format(config.read_count_prefix),
            'description': 'Merged clusters from overlapping reads ({})'.format(config.read_count_desc),
            'min': 0,
            'scale': 'PuRd',
            'modify': lambda x: x * config.read_count_multiplier,
            'shared_key': 'read_count'
        }
        self.general_stats_addcols(self.leehom_data, headers)
1088665
def tophat_general_stats_table(self):
        

        headers = OrderedDict()
        headers['overall_aligned_percent'] = {
            'title': '% Aligned',
            'description': 'overall read mapping rate',
            'max': 100,
            'min': 0,
            'suffix': '%',
            'scale': 'YlGn'
        }
        headers['aligned_not_multimapped_discordant'] = {
            'title': '{} Aligned'.format(config.read_count_prefix),
            'description': 'Aligned reads, not multimapped or discordant ({})'.format(config.read_count_desc),
            'min': 0,
            'scale': 'PuRd',
            'modify': lambda x: x * config.read_count_multiplier,
            'shared_key': 'read_count'
        }
        self.general_stats_addcols(self.tophat_data, headers)
701388
def parse_reports(self):
    

    # Set up vars
    self.picard_insertSize_data = dict()
    self.picard_insertSize_histogram = dict()
    self.picard_insertSize_samplestats = dict()

    # Go through logs and find Metrics
    for f in self.find_log_files('picard/insertsize', filehandles=True):
        s_name = None
        in_hist = False
        for l in f['f']:

            # Catch the histogram values
            if s_name is not None and in_hist is True:
                try:
                    sections = l.split("\t")
                    ins = int(sections[0])
                    tot_count = sum( [int(x) for x in sections[1:]] )
                    self.picard_insertSize_histogram[s_name][ins] = tot_count
                    self.picard_insertSize_samplestats[s_name]['total_count'] += tot_count
                except ValueError:
                    # Reset in case we have more in this log file
                    s_name = None
                    in_hist = False

            # New log starting
            if 'InsertSizeMetrics' in l and 'INPUT' in l:
                s_name = None
                # Pull sample name from input
                fn_search = re.search(r"INPUT(?:=|\s+)(\[?[^\s]+\]?)", l, flags=re.IGNORECASE)
                if fn_search:
                    s_name = os.path.basename(fn_search.group(1).strip('[]'))
                    s_name = self.clean_s_name(s_name, f['root'])

            if s_name is not None:
                if 'InsertSizeMetrics' in l and '## METRICS CLASS' in l:
                    if s_name in self.picard_insertSize_data:
                        log.debug("Duplicate sample name found in {}! Overwriting: {}".format(f['fn'], s_name))
                    self.add_data_source(f, s_name, section='InsertSizeMetrics')
                    keys = f['f'].readline().strip("\n").split("\t")
                    vals = f['f'].readline().strip("\n").split("\t")
                    self.picard_insertSize_samplestats[s_name] = {'total_count': 0, 'meansum':0, 'total_pairs':0 }
                    orientation_idx = keys.index('PAIR_ORIENTATION')
                    while len(vals) == len(keys):
                        pair_orientation = vals[orientation_idx]
                        rowkey = '{}_{}'.format(s_name, pair_orientation)
                        self.picard_insertSize_data[rowkey] = OrderedDict()
                        self.picard_insertSize_data[rowkey]['SAMPLE_NAME'] = s_name
                        for i, k in enumerate(keys):
                            try:
                                self.picard_insertSize_data[rowkey][k] = float(vals[i])
                            except ValueError:
                                try:
                                    self.picard_insertSize_data[rowkey][k] = float(vals[i].replace(',','.'))
                                    log.debug("Switching commas for points in '{}': {} - {}".format(f['fn'], vals[i], vals[i].replace(',','.')))
                                except ValueError:
                                    self.picard_insertSize_data[rowkey][k] = vals[i]
                            except IndexError:
                                pass # missing data
                        # Add to mean sums
                        rp = self.picard_insertSize_data[rowkey]['READ_PAIRS']
                        mis = self.picard_insertSize_data[rowkey]['MEAN_INSERT_SIZE']
                        self.picard_insertSize_samplestats[s_name]['meansum'] += (rp * mis)
                        self.picard_insertSize_samplestats[s_name]['total_pairs'] += rp

                        vals = f['f'].readline().strip("\n").split("\t")

                    # Skip lines on to histogram
                    l = f['f'].readline().strip("\n")
                    l = f['f'].readline().strip("\n")

                    self.picard_insertSize_histogram[s_name] = OrderedDict()
                    in_hist = True

        for key in list(self.picard_insertSize_data.keys()):
            if len(self.picard_insertSize_data[key]) == 0:
                self.picard_insertSize_data.pop(key, None)
        for s_name in list(self.picard_insertSize_histogram.keys()):
            if len(self.picard_insertSize_histogram[s_name]) == 0:
                self.picard_insertSize_histogram.pop(s_name, None)
                log.debug("Ignoring '{}' histogram as no data parsed".format(s_name))

    # Calculate summed mean values for all read orientations
    for s_name, v in self.picard_insertSize_samplestats.items():
        self.picard_insertSize_samplestats[s_name]['summed_mean'] = v['meansum'] / v['total_pairs']

    # Calculate summed median values for all read orientations
    for s_name in self.picard_insertSize_histogram:
        j = 0
        for idx, c in self.picard_insertSize_histogram[s_name].items():
            j += c
            if j > (self.picard_insertSize_samplestats[s_name]['total_count'] / 2):
                self.picard_insertSize_samplestats[s_name]['summed_median'] = idx
                break


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

    if len(self.picard_insertSize_data) > 0:

        # Write parsed data to a file
        self.write_data_file(self.picard_insertSize_data, 'multiqc_picard_insertSize')

        # Do we have median insert sizes?
        missing_medians = False
        for v in self.picard_insertSize_samplestats.values():
            if 'summed_median' not in v:
                missing_medians = True

        # Add to general stats table
        self.general_stats_headers['summed_median'] = {
            'title': 'Insert Size',
            'description': 'Median Insert Size, all read orientations (bp)',
            'min': 0,
            'suffix': ' bp',
            'format': '{:,.0f}',
            'scale': 'GnBu',
        }
        self.general_stats_headers['summed_mean'] = {
            'title': 'Mean Insert Size',
            'description': 'Mean Insert Size, all read orientations (bp)',
            'min': 0,
            'suffix': ' bp',
            'format': '{:,.0f}',
            'scale': 'GnBu',
            'hidden': False if missing_medians else True
        }
        for s_name in self.picard_insertSize_samplestats:
            if s_name not in self.general_stats_data:
                self.general_stats_data[s_name] = dict()
            self.general_stats_data[s_name].update( self.picard_insertSize_samplestats[s_name] )

        # Section with histogram plot
        if len(self.picard_insertSize_histogram) > 0:
            # Make a normalised percentage version of the data
            data_percent = {}
            for s_name, data in self.picard_insertSize_histogram.items():
                data_percent[s_name] = OrderedDict()
                total = float( sum( data.values() ) )
                for k, v in data.items():
                    data_percent[s_name][k] = (v/total)*100

            # Allow customisation of how smooth the the plot is
            try:
                insertsize_smooth_points = int(config.picard_config['insertsize_smooth_points'])
                log.debug("Custom Picard insert size smoothing: {}".format(insertsize_smooth_points))
            except (AttributeError, KeyError, ValueError):
                insertsize_smooth_points = 500

            # Plot the data and add section
            pconfig = {
                'smooth_points': insertsize_smooth_points,
                'smooth_points_sumcounts': [True, False],
                'id': 'picard_insert_size',
                'title': 'Picard: Insert Size',
                'ylab': 'Count',
                'xlab': 'Insert Size (bp)',
                'xDecimals': False,
                'tt_label': '<b>{point.x} bp</b>: {point.y:.0f}',
                'ymin': 0,
                'data_labels': [
                    {'name': 'Counts', 'ylab': 'Coverage'},
                    {'name': 'Percentages', 'ylab': 'Percentage of Counts'}
                ]
            }
            self.add_section (
                name = 'Insert Size',
                anchor = 'picard-insertsize',
                description = 'Plot shows the number of reads at a given insert size. Reads with different orientations are summed.',
                plot = linegraph.plot([self.picard_insertSize_histogram, data_percent], pconfig)
            )


    # Return the number of detected samples to the parent module
    return len(self.picard_insertSize_data)
350613
def AddAnalysisReport(self, analysis_report):
    
    self._RaiseIfNotWritable()

    self._storage_file.AddAnalysisReport(analysis_report)

    report_identifier = analysis_report.plugin_name
    self._session.analysis_reports_counter['total'] += 1
    self._session.analysis_reports_counter[report_identifier] += 1
    self.number_of_analysis_reports += 1
794645
def add_stats(self, args):
        """"""
        bg_name, stats = args
        logger.debug("Stats: %s %s", bg_name, stats)
        
        for motif_id in stats.keys():
            if motif_id not in self.stats:
                self.stats[motif_id] = {}
        
            self.stats[motif_id][bg_name] = stats[motif_id]
188837
def parse_reports(self):
    

    # Set up vars
    self.bam_stat_data = dict()
    regexes = {
        'total_records': r"Total records:\s*(\d+)",
        'qc_failed': r"QC failed:\s*(\d+)",
        'optical_pcr_duplicate': r"Optical/PCR duplicate:\s*(\d+)",
        'non_primary_hits': r"Non primary hits\s*(\d+)",
        'unmapped_reads': r"Unmapped reads:\s*(\d+)",
        'mapq_lt_mapq_cut_non-unique': r"mapq < mapq_cut \(non-unique\):\s*(\d+)",
        'mapq_gte_mapq_cut_unique': r"mapq >= mapq_cut \(unique\):\s*(\d+)",
        'read_1': r"Read-1:\s*(\d+)",
        'read_2': r"Read-2:\s*(\d+)",
        'reads_map_to_sense': r"Reads map to '\+':\s*(\d+)",
        'reads_map_to_antisense': r"Reads map to '-':\s*(\d+)",
        'non-splice_reads': r"Non-splice reads:\s*(\d+)",
        'splice_reads': r"Splice reads:\s*(\d+)",
        'reads_mapped_in_proper_pairs': r"Reads mapped in proper pairs:\s*(\d+)",
        'proper-paired_reads_map_to_different_chrom': r"Proper-paired reads map to different chrom:\s*(\d+)",
    }

    #intiate PE check
    is_paired_end=False

    # Go through files and parse data using regexes
    for f in self.find_log_files('rseqc/bam_stat'):
        d = dict()
        for k, r in regexes.items():
            r_search = re.search(r, f['f'], re.MULTILINE)
            if r_search:
                d[k] = int(r_search.group(1))

        # Calculate some percentages
        if 'total_records' in d:
            t = float(d['total_records'])
            if 'mapq_gte_mapq_cut_unique' in d:
                d['unique_percent'] = (float(d['mapq_gte_mapq_cut_unique']) / t)*100.0
            if 'reads_mapped_in_proper_pairs' in d:
                d['proper_pairs_percent'] = (float(d['reads_mapped_in_proper_pairs']) / t)*100.0

        if len(d) > 0:
            if f['s_name'] in self.bam_stat_data:
                log.debug("Duplicate sample name found! Overwriting: {}".format(f['s_name']))
            self.add_data_source(f, section='bam_stat')
            #Check if SE or PE
            if d['read_2'] != 0:
                is_paired_end = True
            self.bam_stat_data[f['s_name']] = d

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

    if len(self.bam_stat_data) > 0:
        # Write to file
        self.write_data_file(self.bam_stat_data, 'multiqc_rseqc_bam_stat')

        # Add to general stats table
        self.general_stats_headers['proper_pairs_percent'] = {
            'title': '% Proper Pairs',
            'description': '% Reads mapped in proper pairs',
            'max': 100,
            'min': 0,
            'suffix': '%',
            'scale': 'RdYlGn'
        }
        for s_name in self.bam_stat_data:
            if s_name not in self.general_stats_data:
                self.general_stats_data[s_name] = dict()

                #Only write if PE, i.e. there is something to write
                if is_paired_end:
                    self.general_stats_data[s_name].update( self.bam_stat_data[s_name] )

        # Make dot plot of counts
        pconfig = {
            'id': 'rseqc_bam_stat'
        }
        keys = OrderedDict()
        defaults = {
            'min': 0,
            'shared_key': 'read_count',
            'decimalPlaces': 2,
            'modify': lambda x: float(x) / 1000000.0,
        }
        keys['total_records'] = dict(defaults, **{'title': 'Total records' })
        keys['qc_failed'] = dict(defaults, **{'title': 'QC failed' })
        keys['optical_pcr_duplicate'] = dict(defaults, **{'title': 'Duplicates', 'description': 'Optical/PCR duplicate' })
        keys['non_primary_hits'] = dict(defaults, **{'title': 'Non primary hit' })
        keys['unmapped_reads'] = dict(defaults, **{'title': 'Unmapped', 'description': 'Unmapped reads' })
        keys['mapq_lt_mapq_cut_non'] = dict(defaults, **{'title': 'Non-unique', 'description': 'mapq < mapq_cut (non-unique)' })
        keys['mapq_gte_mapq_cut_unique'] = dict(defaults, **{'title': 'Unique', 'description': 'mapq >= mapq_cut (unique)' })
        if is_paired_end:
            keys['read_1'] = dict(defaults, **{'title': 'Read-1' })
            keys['read_2'] = dict(defaults, **{'title': 'Read-2' })
        keys['reads_map_to_sense'] = dict(defaults, **{'title': '+ve strand', 'description': "Reads map to '+'" })
        keys['reads_map_to_antisense'] = dict(defaults, **{'title': '-ve strand', 'description': "Reads map to '-'" })
        keys['non-splice_reads'] = dict(defaults, **{'title': 'Non-splice reads' })
        keys['splice_reads'] = dict(defaults, **{'title': 'Splice reads' })
        if is_paired_end:
            keys['reads_mapped_in_proper_pairs'] = dict(defaults, **{
                        'title': 'Proper pairs', 'description':'Reads mapped in proper pairs' })
            keys['proper-paired_reads_map_to_different_chrom'] = dict(defaults, **{
                        'title': 'Different chrom', 'description': 'Proper-paired reads map to different chrom' })

        self.add_section (
            name = 'Bam Stat',
            anchor = 'rseqc-bam_stat',
            description = 'All numbers reported in millions.',
            plot = beeswarm.plot(self.bam_stat_data, keys, pconfig)
        )

    # Return number of samples found
    return len(self.bam_stat_data)
259841
def _add_stats_box(h1: Histogram1D, ax: Axes, stats: Union[str, bool] = "all"):
    

    # place a text box in upper left in axes coords
    if stats in ["all", True]:
        text = "Total: {0}\nMean: {1:.2f}\nStd.dev: {2:.2f}".format(
            h1.total, h1.mean(), h1.std())
    elif stats == "total":
        text = "Total: {0}".format(h1.total)
    else:
        raise ValueError("Invalid stats specification")
        
    ax.text(0.05, 0.95, text, transform=ax.transAxes,
            verticalalignment='top', horizontalalignment='left')
1232148
def parse_reports(parent_module):
    

    # get data
    data = collect_data(parent_module)

    # Filter to strip out ignored sample names
    data = parent_module.ignore_samples(data)

    # Reference data in parent module
    parent_module.picard_variantCalling_data = data

    if len(data) > 0:
        derive_data(data)

        # Write parsed data to a file
        parent_module.write_data_file(data, 'multiqc_picard_varientCalling')

        parent_module.general_stats_headers['DBSNP_TITV'] = {
            'title': 'TiTV ratio (known)',
            'description': "The Transition/Transversion ratio of the passing bi-allelic SNP calls made at SNP-database sites.",
            'min': 0,
            'scale': 'Blues',
            'shared_key': 'titv_ratio'
        }

        parent_module.general_stats_headers['NOVEL_TITV'] = {
            'title': 'TiTV ratio (novel)',
            'description': "The Transition/Transversion ratio of the passing bi-allelic SNP calls made at non-SNP-database sites.",
            'min': 0,
            'scale': 'Blues',
            'shared_key': 'titv_ratio'
        }

        parent_module.general_stats_headers['DBSNP_INS_DEL_RATIO'] = {
            'title': 'InDel ratio (known)',
            'description': "The Insertion / Deletion ratio of the passing bi-allelic SNP calls made at SNP-database sites.",
            'min': 0,
            'scale': 'Greens',
            'shared_key': 'indel_ratio',
            'hidden': True,
        }

        parent_module.general_stats_headers['NOVEL_INS_DEL_RATIO'] = {
            'title': 'InDel ratio (novel)',
            'description': "The Insertion / Deletion ratio of the passing bi-allelic SNP calls made at non-SNP-database sites.",
            'min': 0,
            'scale': 'Greens',
            'shared_key': 'indel_ratio',
            'hidden': True,
        }


        parent_module.general_stats_headers['total_called_variants_known'] = {
            'title': 'Called Variants (known)',
            'description': "Total counts of variants in SNP-database sites.",
            'shared_key': 'variant_count',
            'min': 0,
            'format': '{0:,.0f}',
            'hidden': True,
        }

        parent_module.general_stats_headers['total_called_variants_novel'] = {
            'title': 'Called Variants (novel)',
            'description': "Total counts of variants in non-SNP-database sites.",
            'shared_key': 'variant_count',
            'min': 0,
            'format': '{0:,.0f}',
            'hidden': True,
        }

        for s_name in data:
            if s_name not in parent_module.general_stats_data:
                parent_module.general_stats_data[s_name] = dict()
            parent_module.general_stats_data[s_name].update(data[s_name])


        # Variant Counts Bargraph
        parent_module.add_section(
            name='Variant Types',
            anchor='picard-variants-types',
            description='Variants that have been called, looking at variant types. Optionally filtered on label.',
            helptext="""
            Only passing variants are shown (i.e. non-filtered).\n
            SNPs are bi-allelic.\n
            Complex InDels are both an insertion and a deletion.
            """,
            plot=compare_variant_type_plot(data)
        )

        # Variant Counts Table
        parent_module.add_section(
            name='Variant Labels',
            anchor='picard-variants-labels',
            description='Variants that have been called, comparing with known variant sites.',
            helptext="""
            Only passing variants are shown (i.e. non-filtered).\n
            Variants contain bi-allelic SNPs, multi-allelic SNPs, simple and complex inserts and deletions.
            """,
            plot=compare_variants_label_plot(data)
        )

    return len(data)
356972
def _AddsAnalysisProcessStatusTableRow(self, process_status, table_view):
    
    used_memory = self._FormatSizeInUnitsOf1024(process_status.used_memory)

    events = ''
    if (process_status.number_of_consumed_events is not None and
        process_status.number_of_consumed_events_delta is not None):
      events = '{0:d} ({1:d})'.format(
          process_status.number_of_consumed_events,
          process_status.number_of_consumed_events_delta)

    event_tags = ''
    if (process_status.number_of_produced_event_tags is not None and
        process_status.number_of_produced_event_tags_delta is not None):
      event_tags = '{0:d} ({1:d})'.format(
          process_status.number_of_produced_event_tags,
          process_status.number_of_produced_event_tags_delta)

    reports = ''
    if (process_status.number_of_produced_reports is not None and
        process_status.number_of_produced_reports_delta is not None):
      reports = '{0:d} ({1:d})'.format(
          process_status.number_of_produced_reports,
          process_status.number_of_produced_reports_delta)

    table_view.AddRow([
        process_status.identifier, process_status.pid, process_status.status,
        used_memory, events, event_tags, reports])
526919
def append_stat_var(self, name, get_func):
        
        self._stats_getters.append(get_func)
        self._stats_logline += '%s: {}. ' % name
        self._stats_logline_totals += 'Total %s: {}. ' % name
806211
def make_statistics_information(info):
  """"""
  if not info.splits.total_num_examples:
    # That means that we have yet to calculate the statistics for this.
    return "None computed"

  stats = [(info.splits.total_num_examples, "ALL")]
  for split_name, split_info in info.splits.items():
    stats.append((split_info.num_examples, split_name.upper()))
  # Sort reverse on number of examples.
  stats.sort(reverse=True)
  stats = "\n".join([
      "{0:10} | {1:>10,}".format(name, num_exs) for (num_exs, name) in stats
  ])
  return STATISTICS_TABLE.format(split_statistics=stats)
170683
def _GenerateStatsTable(self, feed_merger):
    
    rows = []
    rows.append('<tr><th class="header"/><th class="header">Merged</th>'
                '<th class="header">Copied from old feed</th>'
                '<th class="header">Copied from new feed</th></tr>')
    for merger in feed_merger.GetMergerList():
      stats = merger.GetMergeStats()
      if stats is None:
        continue
      merged, not_merged_a, not_merged_b = stats
      rows.append('<tr><th class="header">%s</th>'
                  '<td class="header">%d</td>'
                  '<td class="header">%d</td>'
                  '<td class="header">%d</td></tr>' %
                  (merger.DATASET_NAME, merged, not_merged_a, not_merged_b))
    return '<table>%s</table>' % '\n'.join(rows)
852617
def _populate_basic_data(mfg_event, record):
  """"""
  # TODO:
  #   * Missing in proto: set run name from metadata.
  #   * `part_tags` field on proto is unused
  #   * `timings` field on proto is unused.
  #   * Handle arbitrary units as uom_code/uom_suffix.

  # Populate non-repeated fields.
  mfg_event.dut_serial = record.dut_id
  mfg_event.start_time_ms = record.start_time_millis
  mfg_event.end_time_ms = record.end_time_millis
  mfg_event.tester_name = record.station_id
  mfg_event.test_name = record.metadata.get('test_name') or record.station_id
  mfg_event.test_status = test_runs_converter.OUTCOME_MAP[record.outcome]
  mfg_event.operator_name = record.metadata.get('operator_name', '')
  mfg_event.test_version = str(record.metadata.get('test_version', ''))
  mfg_event.test_description = record.metadata.get('test_description', '')

  # Populate part_tags.
  mfg_event.part_tags.extend(record.metadata.get('part_tags', []))

  # Populate phases.
  for phase in record.phases:
    mfg_phase = mfg_event.phases.add()
    mfg_phase.name = phase.name
    mfg_phase.description = phase.codeinfo.sourcecode
    mfg_phase.timing.start_time_millis = phase.start_time_millis
    mfg_phase.timing.end_time_millis = phase.end_time_millis

  # Populate failure codes.
  for details in record.outcome_details:
    failure_code = mfg_event.failure_codes.add()
    failure_code.code = details.code
    failure_code.details = details.description

  # Populate test logs.
  for log_record in record.log_records:
    test_log = mfg_event.test_logs.add()
    test_log.timestamp_millis = log_record.timestamp_millis
    test_log.log_message = log_record.message
    test_log.logger_name = log_record.logger_name
    test_log.levelno = log_record.level
    if log_record.level <= logging.DEBUG:
      test_log.level = test_runs_pb2.TestRunLogMessage.DEBUG
    elif log_record.level <= logging.INFO:
      test_log.level = test_runs_pb2.TestRunLogMessage.INFO
    elif log_record.level <= logging.WARNING:
      test_log.level = test_runs_pb2.TestRunLogMessage.WARNING
    elif log_record.level <= logging.ERROR:
      test_log.level = test_runs_pb2.TestRunLogMessage.ERROR
    elif log_record.level <= logging.CRITICAL:
      test_log.level = test_runs_pb2.TestRunLogMessage.CRITICAL
    test_log.log_source = log_record.source
    test_log.lineno = log_record.lineno
741401
def set_stats(stats, value):
    
    stats["total_count"] += 1
    stats["value"] += value
    stats["average"] = stats["value"] / stats["total_count"]

    # this is just a basic example and not the best way to track aggregation.
    # for max and min old there are cases where this will not work correctly.
    if value > stats["max"]:
        stats["max"] = value

    if value < stats["min"] or stats["min"] == 0:
        stats["min"] = value
154712
def update_from_stats(self, stats):
        """"""

        sd = dict(stats)

        for c in self.columns:

            if c not in sd:
                continue

            stat = sd[c]

            if stat.size and stat.size > c.size:
                c.size = stat.size

            c.lom = stat.lom
634391
def report(self):
        """"""
        # Initialise strings to store report data
        header = '\t'.join(self.headers) + '\n'
        data = ''
        for sample in self.metadata:
            if sample.general.bestassemblyfile != 'NA':
                # Each strain is a fresh row
                row = ''
                try:
                    # Read in the output .json file into the metadata
                    sample[self.analysistype].jsondata = json.load(open(sample[self.analysistype].jsonoutput, 'r'))
                    # Set the name of the report.
                    # Note that this is a tab-separated file, as there can be commas in the results
                    sample[self.analysistype].report = os.path.join(sample[self.analysistype].reportdir,
                                                                    '{}.tsv'.format(sample.name))
                    # Iterate through all the headers to use as keys in the json-formatted output
                    for category in self.headers:
                        # Tab separate all the results
                        row += '{}\t'.format(sample[self.analysistype].jsondata[0][category])
                        # Create attributes for each category
                        setattr(sample[self.analysistype], category,
                                str(sample[self.analysistype].jsondata[0][category]))
                    # End the results with a newline
                    row += '\n'

                    data += row
                    # Create and write headers and results to the strain-specific report
                    with open(sample[self.analysistype].report, 'w') as strainreport:
                        strainreport.write(header)
                        strainreport.write(row)
                except (KeyError, AttributeError):
                    pass
            # Create and write headers and cumulative results to the combined report
            with open(os.path.join(self.reportdir, 'sistr.tsv'), 'w') as report:
                report.write(header)
                report.write(data)
604961
def addSummaryMetrics(self, dict_to_plot):
        

        headers = OrderedDict()

        headers['std'] = {
            'title': 'Read length std. dev.',
            'description': 'Read length std. dev.',
            'suffix': 'bp',
            'scale': 'PuBu',
            'format': '{:,.2f}',
            'shared_key': 'read_length',
            'hidden': True
        }

        headers['median'] = {
            'title': 'Median read length',
            'description': 'Median read length',
            'suffix': 'bp',
            'scale': 'YlGnBu',
            'format': '{:,.2f}',
            'shared_key': 'read_length'
        }
        headers['mean_readlength'] = {
            'title': 'Mean read length',
            'description': 'Mean read length',
            'suffix': 'bp',
            'scale': 'PuBuGn',
            'format': '{:,.2f}',
            'shared_key': 'read_length',
            'hidden': True
        }

        self.general_stats_addcols(dict_to_plot, headers)