parameters: (read_count, stats_total, params=None, out=sys.stdout)
docstring: Take the read count, the accumulated total stats dict, and an optional dict
      of mapping parameters corresponding to values for filters.
      
      Print a nicely formatted table to the given stream.
docstring_summary: Take the read count, the accumulated total stats dict, and an optional dict
      of mapping parameters corresponding to values for filters.
      
      Print a nicely formatted table to the given stream.
docstring_tokens: Take the read count the accumulated total stats dict and an optional dict of mapping parameters corresponding to values for filters . Print a nicely formatted table to the given stream .
function: def print_table(read_count, stats_total, params=None, out=sys.stdout):
      """
      Take the read count, the accumulated total stats dict, and an optional dict
      of mapping parameters corresponding to values for filters.
      
      Print a nicely formatted table to the given stream.
      
      """
      
      if stats_total is None:
          # Handle the empty case
          assert(read_count == 0)
          out.write('No reads.\n')
          return
      
      # Now do a table
      
      # First header line for each column
      headers = []
      # Second header line for wach column
      headers2 = []
      # Column min widths from headers
      header_widths = []
      
      # Compute filter row headings
      filter_headings = stats_total.keys()
      
      if params is not None:
          # Annotate each filter with its parameter value
          annotated_headings = []
          for heading in filter_headings:
              # For each filter
              # It may be a compound thing||thing filter
              parts = heading.split('||')
              
              # We will fill this with all the relevant filter cutoff values
              filter_values = []
              for part in parts:
                  if part in params:
                      filter_values.append(params[part])
                      
              if len(filter_values) == 0:
                  # No parameters
                  annotated_headings.append(heading)
              else:
                  # Annotate with the parameters
                  annotated_headings.append('{} ({})'.format(heading, ', '.join((str(x) for x in filter_values))))
                  
          filter_headings = annotated_headings
      
      # How long is the longest filter name
      filter_width = max((len(x) for x in filter_headings))
      # Leave room for the header
      filter_header = "Filter"
      filter_width = max(filter_width, len(filter_header))
      # And for the "Overall" entry
      filter_overall = "Overall"
      filter_width = max(filter_width, len(filter_overall))
      
      headers.append(filter_header)
      headers2.append('')
      header_widths.append(filter_width)
      
      # And the passing count columns (average)
      passing_header = "Passing"
      passing_header2 = "(/Read)"
      passing_width = max(len(passing_header), len(passing_header2))
      
      headers.append(passing_header)
      headers2.append(passing_header2)
      header_widths.append(passing_width)
      
      # And the failing count columns (average)
      failing_header = "Failing"
      failing_header2 = "(/Read)"
      failing_width = max(len(failing_header), len(failing_header2))
      
      headers.append(failing_header)
      headers2.append(failing_header2)
      header_widths.append(failing_width)
      
      # And the number of correct reads lost at each stage
      lost_stage_header = "Lost"
      lost_stage_header2 = "reads"
      lost_stage_reads = [x for x in (stats_total[filter_name].get('last_correct_stage', 0) for filter_name in stats_total.keys()) if x is not None]
      max_stage = max(lost_stage_reads)
      overall_lost_stage = sum(lost_stage_reads)
      lost_stage_width = max(len(lost_stage_header), len(lost_stage_header2), len(str(max_stage)), len(str(overall_lost_stage)))
      
      headers.append(lost_stage_header)
      headers2.append(lost_stage_header2)
      header_widths.append(lost_stage_width)
  
      # And the correct result lost count header
      lost_header = "Lost"
      lost_header2 = ""
      # How big a number will we need to hold?
      # Look at the reads lost at all filters
      # Account for None values for stages that don't have correctness defined yet.
      lost_reads = [x for x in (stats_total[filter_name]['failed_count_correct'] for filter_name in stats_total.keys()) if x is not None]
      max_filter_stop = max(lost_reads)
      # How many correct reads are lost overall by filters?
      overall_lost = sum(lost_reads)
      lost_width = max(len(lost_header), len(lost_header2), len(str(max_filter_stop)), len(str(overall_lost)))
      
      headers.append(lost_header)
      headers2.append(lost_header2)
      header_widths.append(lost_width)
      
      # And the total rejected count header
      rejected_header = "Cut"
      rejected_header2 = ""
      # How big a number will we need to hold?
      # Look at the reads rejected at all filters
      rejected_reads = [stats_total[filter_name]['failed_count_total'] for filter_name in stats_total.keys()]
      max_filter_stop = max(rejected_reads)
      # How many incorrect reads are rejected overall by filters?
      overall_rejected = sum(rejected_reads)
      rejected_width = max(len(rejected_header), len(rejected_header2), len(str(max_filter_stop)), len(str(overall_rejected)))
      
      headers.append(rejected_header)
      headers2.append(rejected_header2)
      header_widths.append(rejected_width)
      
      # Now do precision and recall
      # How should we format them?
      pr_format = '{:.2f}'
      precision_header = "P"
      precision_header2 = ""
      precision_width = max(len(precision_header), len(precision_header2), len(pr_format.format(1.0)), len('N/A'))
      headers.append(precision_header)
      headers2.append(precision_header2)
      header_widths.append(precision_width)
      recall_header = "R"
      recall_header2 = ""
      recall_width = max(len(recall_header), len(recall_header2), len(pr_format.format(1.0)), len('N/A'))
      headers.append(recall_header)
      headers2.append(recall_header2)
      header_widths.append(recall_width)
      
      
      # Start the table
      table = Table(header_widths)
      
      table.row(["Giraffe Facts"], 'c', merge=[len(header_widths)])
      table.line()
      table.row(['Reads' + str(read_count).rjust(table.inner_width() - 5)], merge=[len(header_widths)])
      table.line()
      table.row(headers, 'c')
      table.row(headers2, 'c')
      table.line()
      
      
      for i, filter_name in enumerate(stats_total.keys()):
          # Grab average results passing this filter per read
          total_passing = stats_total[filter_name]['passed_count_total']
          average_passing = total_passing / read_count if read_count != 0 else float('NaN')
          
          # Grab average results failing this filter per read
          total_failing = stats_total[filter_name]['failed_count_total']
          average_failing = total_failing / read_count if read_count != 0 else float('NaN')
          
          # Grab reads that are lost.
          # No reads are lost at the final stage.
          lost = stats_total[filter_name]['failed_count_correct']
          
          lost_stage = stats_total[filter_name]['last_correct_stage']
  
          # And reads that are rejected at all
          rejected = stats_total[filter_name]['failed_count_total']
          
          if lost is None:
              # Correctness is not defined yet.
              # TODO: have a way to see if the correct mapping never shows up.
              lost = 'N/A'
              
          # Compute precision
          try:
              precision = pr_format.format(stats_total[filter_name]['passed_count_correct'] /
                  stats_total[filter_name]['passed_count_total'])
          except:
              precision = 'N/A'
          
          # Compute recall
          try:
              recall = pr_format.format(stats_total[filter_name]['passed_count_correct'] / 
                  (stats_total[filter_name]['passed_count_correct'] +
                  stats_total[filter_name]['failed_count_correct']))
          except:
              recall = 'N/A'
          
          row = [filter_headings[i]]
          align = 'c'
          # Add the provenance columns
          row += ['{:.2f}'.format(average_passing), '{:.2f}'.format(average_failing), lost_stage, lost, rejected,
              precision, recall]
          align += 'rrrrrr'
          
          # Output the finished row
          table.row(row, align)
          
      table.line()
          
      # Compose the overall row
      row = [filter_overall]
      align = 'c'
      # Add the provenance columns
      row += ['', '', overall_lost_stage, overall_lost, overall_rejected, '', '']
      align += 'rr'
      
      table.row(row, align)
      
      # Close off table
      table.close()
function_tokens: def print_table ( read_count , stats_total , params = None , out = sys . stdout ) : if stats_total is None : # Handle the empty case assert ( read_count == 0 ) out . write ( 'No reads.\n' ) return # Now do a table # First header line for each column headers = [ ] # Second header line for wach column headers2 = [ ] # Column min widths from headers header_widths = [ ] # Compute filter row headings filter_headings = stats_total . keys ( ) if params is not None : # Annotate each filter with its parameter value annotated_headings = [ ] for heading in filter_headings : # For each filter # It may be a compound thing||thing filter parts = heading . split ( '||' ) # We will fill this with all the relevant filter cutoff values filter_values = [ ] for part in parts : if part in params : filter_values . append ( params [ part ] ) if len ( filter_values ) == 0 : # No parameters annotated_headings . append ( heading ) else : # Annotate with the parameters annotated_headings . append ( '{} ({})' . format ( heading , ', ' . join ( ( str ( x ) for x in filter_values ) ) ) ) filter_headings = annotated_headings # How long is the longest filter name filter_width = max ( ( len ( x ) for x in filter_headings ) ) # Leave room for the header filter_header = "Filter" filter_width = max ( filter_width , len ( filter_header ) ) # And for the "Overall" entry filter_overall = "Overall" filter_width = max ( filter_width , len ( filter_overall ) ) headers . append ( filter_header ) headers2 . append ( '' ) header_widths . append ( filter_width ) # And the passing count columns (average) passing_header = "Passing" passing_header2 = "(/Read)" passing_width = max ( len ( passing_header ) , len ( passing_header2 ) ) headers . append ( passing_header ) headers2 . append ( passing_header2 ) header_widths . append ( passing_width ) # And the failing count columns (average) failing_header = "Failing" failing_header2 = "(/Read)" failing_width = max ( len ( failing_header ) , len ( failing_header2 ) ) headers . append ( failing_header ) headers2 . append ( failing_header2 ) header_widths . append ( failing_width ) # And the number of correct reads lost at each stage lost_stage_header = "Lost" lost_stage_header2 = "reads" lost_stage_reads = [ x for x in ( stats_total [ filter_name ] . get ( 'last_correct_stage' , 0 ) for filter_name in stats_total . keys ( ) ) if x is not None ] max_stage = max ( lost_stage_reads ) overall_lost_stage = sum ( lost_stage_reads ) lost_stage_width = max ( len ( lost_stage_header ) , len ( lost_stage_header2 ) , len ( str ( max_stage ) ) , len ( str ( overall_lost_stage ) ) ) headers . append ( lost_stage_header ) headers2 . append ( lost_stage_header2 ) header_widths . append ( lost_stage_width ) # And the correct result lost count header lost_header = "Lost" lost_header2 = "" # How big a number will we need to hold? # Look at the reads lost at all filters # Account for None values for stages that don't have correctness defined yet. lost_reads = [ x for x in ( stats_total [ filter_name ] [ 'failed_count_correct' ] for filter_name in stats_total . keys ( ) ) if x is not None ] max_filter_stop = max ( lost_reads ) # How many correct reads are lost overall by filters? overall_lost = sum ( lost_reads ) lost_width = max ( len ( lost_header ) , len ( lost_header2 ) , len ( str ( max_filter_stop ) ) , len ( str ( overall_lost ) ) ) headers . append ( lost_header ) headers2 . append ( lost_header2 ) header_widths . append ( lost_width ) # And the total rejected count header rejected_header = "Cut" rejected_header2 = "" # How big a number will we need to hold? # Look at the reads rejected at all filters rejected_reads = [ stats_total [ filter_name ] [ 'failed_count_total' ] for filter_name in stats_total . keys ( ) ] max_filter_stop = max ( rejected_reads ) # How many incorrect reads are rejected overall by filters? overall_rejected = sum ( rejected_reads ) rejected_width = max ( len ( rejected_header ) , len ( rejected_header2 ) , len ( str ( max_filter_stop ) ) , len ( str ( overall_rejected ) ) ) headers . append ( rejected_header ) headers2 . append ( rejected_header2 ) header_widths . append ( rejected_width ) # Now do precision and recall # How should we format them? pr_format = '{:.2f}' precision_header = "P" precision_header2 = "" precision_width = max ( len ( precision_header ) , len ( precision_header2 ) , len ( pr_format . format ( 1.0 ) ) , len ( 'N/A' ) ) headers . append ( precision_header ) headers2 . append ( precision_header2 ) header_widths . append ( precision_width ) recall_header = "R" recall_header2 = "" recall_width = max ( len ( recall_header ) , len ( recall_header2 ) , len ( pr_format . format ( 1.0 ) ) , len ( 'N/A' ) ) headers . append ( recall_header ) headers2 . append ( recall_header2 ) header_widths . append ( recall_width ) # Start the table table = Table ( header_widths ) table . row ( [ "Giraffe Facts" ] , 'c' , merge = [ len ( header_widths ) ] ) table . line ( ) table . row ( [ 'Reads' + str ( read_count ) . rjust ( table . inner_width ( ) - 5 ) ] , merge = [ len ( header_widths ) ] ) table . line ( ) table . row ( headers , 'c' ) table . row ( headers2 , 'c' ) table . line ( ) for i , filter_name in enumerate ( stats_total . keys ( ) ) : # Grab average results passing this filter per read total_passing = stats_total [ filter_name ] [ 'passed_count_total' ] average_passing = total_passing / read_count if read_count != 0 else float ( 'NaN' ) # Grab average results failing this filter per read total_failing = stats_total [ filter_name ] [ 'failed_count_total' ] average_failing = total_failing / read_count if read_count != 0 else float ( 'NaN' ) # Grab reads that are lost. # No reads are lost at the final stage. lost = stats_total [ filter_name ] [ 'failed_count_correct' ] lost_stage = stats_total [ filter_name ] [ 'last_correct_stage' ] # And reads that are rejected at all rejected = stats_total [ filter_name ] [ 'failed_count_total' ] if lost is None : # Correctness is not defined yet. # TODO: have a way to see if the correct mapping never shows up. lost = 'N/A' # Compute precision try : precision = pr_format . format ( stats_total [ filter_name ] [ 'passed_count_correct' ] / stats_total [ filter_name ] [ 'passed_count_total' ] ) except : precision = 'N/A' # Compute recall try : recall = pr_format . format ( stats_total [ filter_name ] [ 'passed_count_correct' ] / ( stats_total [ filter_name ] [ 'passed_count_correct' ] + stats_total [ filter_name ] [ 'failed_count_correct' ] ) ) except : recall = 'N/A' row = [ filter_headings [ i ] ] align = 'c' # Add the provenance columns row += [ '{:.2f}' . format ( average_passing ) , '{:.2f}' . format ( average_failing ) , lost_stage , lost , rejected , precision , recall ] align += 'rrrrrr' # Output the finished row table . row ( row , align ) table . line ( ) # Compose the overall row row = [ filter_overall ] align = 'c' # Add the provenance columns row += [ '' , '' , overall_lost_stage , overall_lost , overall_rejected , '' , '' ] align += 'rr' table . row ( row , align ) # Close off table table . close ( )