Saves statistics about each submission.

    Saved statistics include score; number of completed and failed batches;
    min, max, average and median time needed to run one batch.

    Args:
      run_stats: dictionary with runtime statistics for submissions,
        can be generated by WorkPiecesBase.compute_work_statistics
      scores: dictionary mapping submission ids to scores
      num_processed_images: dictionary with number of successfully processed
        images by each submission, one of the outputs of
        ClassificationBatches.compute_classification_results
      filename: output filename

def _save_work_results(self, run_stats, scores, num_processed_images,
                         filename):
    """Saves statistics about each submission.

    Saved statistics include score; number of completed and failed batches;
    min, max, average and median time needed to run one batch.

    Args:
      run_stats: dictionary with runtime statistics for submissions,
        can be generated by WorkPiecesBase.compute_work_statistics
      scores: dictionary mapping submission ids to scores
      num_processed_images: dictionary with number of successfully processed
        images by each submission, one of the outputs of
        ClassificationBatches.compute_classification_results
      filename: output filename
    """
    with open(filename, 'w') as f:
      writer = csv.writer(f)
      writer.writerow(
          ['SubmissionID', 'ExternalSubmissionId', 'Score',
           'CompletedBatches', 'BatchesWithError', 'ProcessedImages',
           'MinEvalTime', 'MaxEvalTime',
           'MedianEvalTime', 'MeanEvalTime',
           'ErrorMsg'])
      for submission_id in sorted(iterkeys(run_stats)):
        stat = run_stats.get(
            submission_id,
            collections.defaultdict(lambda: float('NaN')))
        external_id = self.submissions.get_external_id(submission_id)
        error_msg = ''
        while not error_msg and stat['error_messages']:
          error_msg = stat['error_messages'].pop()
          if error_msg.startswith('Cant copy adversarial batch locally'):
            error_msg = ''
        writer.writerow([
            submission_id, external_id, scores.get(submission_id, None),
            stat['completed'], stat['num_errors'],
            num_processed_images.get(submission_id, None),
            stat['min_eval_time'], stat['max_eval_time'],
            stat['median_eval_time'], stat['mean_eval_time'],
            error_msg
        ])