Create a new scan report, passing in every attribute. The best way to do
 this is with the ScanResultProcessor module.

 Returns an array representation of the ScanReport. Metadata about the
 scan, and an array of Host arrays comprise the array.
552885
def to_array
      self.instance_variables.map do |var|
        if var == :@hosts
          self.instance_variable_get(var).map {|host| host.to_array}
        else
          self.instance_variable_get(var)
        end
      end
    end
637021
@SuppressWarnings("squid:S134")
    private void createHtmlReport(FilePath reportFolder,
                                  String testFolderPath,
                                  File artifactsDir,
                                  List<String> reportNames,
                                  TestResult testResult) throws IOException, InterruptedException {
        String archiveTestResultMode =
                _resultsPublisherModel.getArchiveTestResultsMode();
        boolean createReport = archiveTestResultMode.equals(ResultsPublisherModel.CreateHtmlReportResults.getValue());


        if (createReport) {
            File testFolderPathFile = new File(testFolderPath);
            FilePath srcDirectoryFilePath = new FilePath(reportFolder, HTML_REPORT_FOLDER);
            if (srcDirectoryFilePath.exists()) {
                FilePath srcFilePath = new FilePath(srcDirectoryFilePath, IE_REPORT_FOLDER);
                if (srcFilePath.exists()) {
                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    srcFilePath.zip(baos);
                    File reportDirectory = new File(artifactsDir.getParent(), PERFORMANCE_REPORT_FOLDER);
                    if (!reportDirectory.exists()) {
                        reportDirectory.mkdir();
                    }
                    ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
                    FilePath reportDirectoryFilePath = new FilePath(reportDirectory);
                    FilePath tmpZipFile = new FilePath(reportDirectoryFilePath, "tmp.zip");
                    tmpZipFile.copyFrom(bais);
                    bais.close();
                    baos.close();
                    tmpZipFile.unzip(reportDirectoryFilePath);
                    String newFolderName = org.apache.commons.io.FilenameUtils.getName(testFolderPathFile.getPath());
                    FileUtils.moveDirectory(new File(reportDirectory, IE_REPORT_FOLDER),
                            new File(reportDirectory, newFolderName));
                    tmpZipFile.delete();
                    outputReportFiles(reportNames, reportDirectory, testResult, false);
                }
            }
        }
    }
733614
def scan(cls, result_key, func):
        

        if result_key in cls.scanner_keys:
            raise ValueError("'%s' is already a registered scanner key" % result_key)

        def scanner(self):
            result = func(self)
            setattr(self, result_key, result)

        cls.scanners.append(scanner)
        cls.scanner_keys.add(result_key)
745753
def scanner
      @scanner ||= Scanner.new(
        @doc.root['scanner'],
        @doc.root['version'],
        @doc.root['args'],
        Time.at(@doc.root['start'].to_i)
      )
    end
455870
def generate(self):
    
    self._setup()

    header_html = self._generate_header()
    footer_html = self._generate_footer()
    results_topbar_html = self._generate_topbar("results")
    summary_topbar_html = self._generate_topbar("summary")
    logs_topbar_html = self._generate_topbar("logs")
    diff_topbar_html = self._generate_topbar("diff")

    summary_body_html = self._generate_summary_body()
    diff_body_html = self._generate_diff_body()
    summary_html = header_html + summary_topbar_html + summary_body_html + footer_html
    diff_html = header_html + diff_topbar_html + diff_body_html+ footer_html
    Reporter._make_file(summary_html, self.report_info.home_page)
    Reporter._make_file(diff_html,self.report_info.diff_page)

    log_body_html = self._generate_log_body()
    log_html = header_html + logs_topbar_html + log_body_html+footer_html
    Reporter._make_file(log_html, self.report_info.log_page)

    for config_name in self.report_info.config_to_test_names_map.keys():
      config_dir = os.path.join(self.report_info.resource_dir, config_name)
      utils.makedirs(config_dir)

      config_body_html = self._generate_config_body(config_name)
      config_html = header_html + results_topbar_html + config_body_html + footer_html
      config_file = os.path.join(config_dir, config_name + self.report_info.report_file_sfx)
      Reporter._make_file(config_html, config_file)

      for test_name in self.data_source.get_test_names(config_name):
        test_body_html = self._generate_test_body(config_name, test_name)
        test_html = header_html + results_topbar_html + test_body_html + footer_html
        test_file = os.path.join(config_dir, test_name + self.report_info.report_file_sfx)
        Reporter._make_file(test_html, test_file)
1182132
def create_result_object(result):
    
    _result = {
        'tcid': result.get_tc_name(),
        'campaign': result.campaign,
        'cre': {
            'user': result.tester
        },
        'job': {
            'id': result.job_id
        },
        'exec': {
            'verdict': result.get_verdict(),
            'duration': result.duration,
            'note': result.get_fail_reason(),
            'dut': {
                'count': result.dut_count,
                'type': result.dut_type
            },
            'sut': {
                'branch': result.build_branch,
                'commitId': result.buildcommit,
                'buildDate': result.build_date,
                'buildSha1': result.build_sha1,
                'buildUrl': result.build_url,
                'gitUrl': result.build_git_url,
                'cut': result.component,  # Component Under Uest
                'fut': result.feature    # Feature Under Test
            },
            'env': {
                'framework': {
                    'name': result.fw_name,
                    'ver': result.fw_version
                }
            },
            "logs": []
        }
    }

    if result.dut_resource_id:
        _result["exec"]["dut"]["sn"] = result.dut_resource_id

    if result.dut_vendor and result.dut_vendor[0]:
        _result["exec"]["dut"]["vendor"] = result.dut_vendor[0]
    if result.dut_models and result.dut_models[0]:
        _result["exec"]["dut"]["model"] = result.dut_models[0]
    # pylint: disable=len-as-condition
    if len(result.dut_models) == 1 and len(result.dut_resource_id) == 1:
        _result["exec"]["dut"]["sn"] = result.dut_resource_id[0]

    return remove_empty_from_dict(_result)
683209
def reports(self):
        
        printtime('Finding reports', self.start)
        # Initialise a list of runs and a list of all the metadata objects
        runs = list()
        samples = list()
        # Glob all the assembly folders into a list
        folders = glob(os.path.join(self.path, '*'.format(self.path)))
        # Iterate through all the folders
        for folder in folders:
            if os.path.isdir(folder):
                # Ignore any previously processed aggregate reports folder
                if 'reports' not in folder:
                    # Treat the external labs differently - instead of having all the assemblies in the path, each lab
                    # has its own subfolder with assemblies
                    if self.external:
                        subfolder = glob(os.path.join(folder, '*'))
                        for subsubfolder in subfolder:
                            if os.path.isdir(subfolder):
                                runs.append(subsubfolder)
                    else:
                        runs.append(folder)
        # Create metadata objects for each assembly run
        for assembly in sorted(runs):
            # Initialise the Metadata object
            metadata = MetadataObject()
            metadata.name = assembly.split('/')[-2] if assembly.split('/')[-3] == 'WGSspades' else '{}-{}'\
                .format(assembly.split('/')[-3], assembly.split('/')[-2])
            # Strip of any underscores and anything after an underscore
            metadata.name = metadata.name.split('_')[0]
            # Initialise Genobjects to store nested dictionaries of metadata in each metadata object
            metadata.general = GenObject()
            # Populate the GenObject
            metadata.general.path = assembly
            metadata.general.reportpath = os.path.join(str(assembly), 'reports')
            metadata.general.reports = glob(os.path.join(metadata.general.reportpath, '*.csv'))
            metadata.general.reportnames = [os.path.basename(x) for x in metadata.general.reports]
            # Add all the names of the reports to the set of reports
            for reportname in metadata.general.reportnames:
                self.reportset.add(reportname)
            # Add the metadata to list of metadata objects
            samples.append(metadata)
        # Return the list of metadata objects
        return samples
32554
private Iterator<Map<String, Object>> queryDataStoreForTableReportResults(final String reportTable, final AllTablesReportQuery query) {
        if (!query.getTableNames().isEmpty()) {
            // Querying for a specific set of tables.
            return Iterators.concat(
                    Iterators.transform(
                            query.getTableNames().iterator(),
                            new Function<String, Map<String, Object>>() {
                                @Override
                                public Map<String, Object> apply(String tableName) {
                                    return _dataStore.get(reportTable, tableName, ReadConsistency.STRONG);
                                }
                            }
                    ));
        }

        // Querying over the full set of tables

        return new AbstractIterator<Map<String, Object>>() {
            private String _from = query.getFromTable();
            private Iterator<Map<String, Object>> _batch = Iterators.emptyIterator();
            private long _limit = 0;

            @Override
            protected Map<String, Object> computeNext() {
                if (!_batch.hasNext()) {
                    if (_limit == 0) {
                        // First iteration get the requested number of results
                        _limit = query.getLimit();
                    } else {
                        // Subsequent requests iterate over all remaining results; dataStore will batch the results
                        _limit = Long.MAX_VALUE;
                    }

                    _batch = _dataStore.scan(reportTable, _from, _limit, false, ReadConsistency.STRONG);
                    if (!_batch.hasNext()) {
                        return endOfData();
                    }
                }

                Map<String, Object> result = _batch.next();
                _from = Intrinsic.getId(result);
                return result;
            }
        };
    }
146552
private List<Flow> createFromResults(Scan scan, boolean populateTasks,
      int maxCount) throws IOException {
    List<Flow> flows = new ArrayList<Flow>();
    ResultScanner scanner = null;
    try {
      Stopwatch timer = new Stopwatch().start();
      Stopwatch timerJob = new Stopwatch();
      int rowCount = 0;
      long colCount = 0;
      long resultSize = 0;
      int jobCount = 0;
      Table historyTable =
          hbaseConnection.getTable(TableName.valueOf(Constants.HISTORY_TABLE));
      scanner = historyTable.getScanner(scan);
      Flow currentFlow = null;
      for (Result result : scanner) {
        if (result != null && !result.isEmpty()) {
          rowCount++;
          colCount += result.size();
          // TODO dogpiledays resultSize += result.getWritableSize();
          JobKey currentKey = jobKeyConv.fromBytes(result.getRow());
          // empty runId is special cased -- we need to treat each job as it's
          // own flow
          if (currentFlow == null || !currentFlow.contains(currentKey)
              || currentKey.getRunId() == 0) {
            // return if we've already hit the limit
            if (flows.size() >= maxCount) {
              break;
            }
            currentFlow = new Flow(new FlowKey(currentKey));
            flows.add(currentFlow);
          }
          timerJob.start();
          JobDetails job = new JobDetails(currentKey);
          job.populate(result);
          currentFlow.addJob(job);
          jobCount++;
          timerJob.stop();
        }
      }
      historyTable.close();
      timer.stop();
      LOG.info("Fetched from hbase " + rowCount + " rows, " + colCount
          + " columns, " + flows.size() + " flows and " + jobCount
          + " jobs taking up " + resultSize + " bytes ( "
          + resultSize / (1024.0 * 1024.0) + " atomic double: "
          + new AtomicDouble(resultSize / (1024.0 * 1024.0))
          + ") MB, in total time of " + timer + " with  " + timerJob
          + " spent inJobDetails & Flow population");

      // export the size of data fetched from hbase as a metric
      HravenResponseMetrics.FLOW_HBASE_RESULT_SIZE_VALUE
          .set(resultSize / (1024.0 * 1024.0));
    } finally {
      if (scanner != null) {
        scanner.close();
      }
    }

    if (populateTasks) {
      populateTasks(flows);
    }

    return flows;
  }
1023140
def parallel_scan(self, scan_id, target):
        
        try:
            ret = self.exec_scan(scan_id, target)
            if ret == 0:
                self.add_scan_host_detail(scan_id, name='host_status',
                                          host=target, value='0')
            elif ret == 1:
                self.add_scan_host_detail(scan_id, name='host_status',
                                          host=target, value='1')
            elif ret == 2:
                self.add_scan_host_detail(scan_id, name='host_status',
                                          host=target, value='2')
            else:
                logger.debug('%s: No host status returned', target)
        except Exception as e:
            self.add_scan_error(scan_id, name='', host=target,
                                value='Host process failure (%s).' % e)
            logger.exception('While scanning %s:', target)
        else:
            logger.info("%s: Host scan finished.", target)
1320229
def get_scan_results_xml(self, scan_id, pop_res):
        
        results = Element('results')
        for result in self.scan_collection.results_iterator(scan_id, pop_res):
            results.append(get_result_xml(result))

        logger.info('Returning %d results', len(results))
        return results
1355395
def create_scan(self, scan_id, targets, options, vts):
        
        if self.scan_exists(scan_id):
            logger.info("Scan %s exists. Resuming scan.", scan_id)

        return self.scan_collection.create_scan(scan_id, targets, options, vts)
745976
@Override
    void setScanResult(final ScanResult scanResult) {
        super.setScanResult(scanResult);
        if (this.typeDescriptor != null) {
            this.typeDescriptor.setScanResult(scanResult);
        }
        if (this.typeSignature != null) {
            this.typeSignature.setScanResult(scanResult);
        }
        if (this.annotationInfo != null) {
            for (final AnnotationInfo ai : this.annotationInfo) {
                ai.setScanResult(scanResult);
            }
        }
        if (this.parameterAnnotationInfo != null) {
            for (final AnnotationInfo[] pai : this.parameterAnnotationInfo) {
                if (pai != null) {
                    for (final AnnotationInfo ai : pai) {
                        ai.setScanResult(scanResult);
                    }
                }
            }
        }
        if (this.parameterInfo != null) {
            for (final MethodParameterInfo mpi : parameterInfo) {
                mpi.setScanResult(scanResult);
            }
        }
    }
454419
def mlstreporter(self):
        
        logging.info('Writing reports')
        # Initialise variables
        header_row = str()
        combinedrow = str()
        combined_header_row = str()
        reportdirset = set()
        mlst_dict = dict()
        # Populate a set of all the report directories to use. A standard analysis will only have a single report
        # directory, while pipeline analyses will have as many report directories as there are assembled samples
        for sample in self.runmetadata.samples:
            if sample.general.bestassemblyfile != 'NA':
                # Ignore samples that lack a populated reportdir attribute
                if sample[self.analysistype].reportdir != 'NA':
                    make_path(sample[self.analysistype].reportdir)
                    # Add to the set - I probably could have used a counter here, but I decided against it
                    reportdirset.add(sample[self.analysistype].reportdir)
        # Create a report for each sample from :self.resultprofile
        for sample in self.runmetadata.samples:
            if sample.general.bestassemblyfile != 'NA':
                if sample[self.analysistype].reportdir != 'NA':
                    if type(sample[self.analysistype].allelenames) == list:
                        # Initialise the string
                        row = str()
                        if self.analysistype == 'mlst':
                            header_row = str()
                            try:
                                if sample.general.referencegenus not in mlst_dict:
                                    mlst_dict[sample.general.referencegenus] = dict()
                            except AttributeError:
                                sample.general.referencegenus = 'ND'
                                mlst_dict[sample.general.referencegenus] = dict()
                        # Additional fields such as clonal complex and lineage
                        additional_fields = list()
                        #
                        if self.meta_headers:
                            for header in self.meta_headers:
                                try:
                                    _ = sample[self.analysistype].meta_dict[
                                        sample[self.analysistype].sequencetype][header]
                                    additional_fields.append(header.rstrip())
                                except (AttributeError, KeyError):
                                    pass
                        if self.analysistype == 'mlst':
                            additional_fields = sorted(additional_fields)
                            #
                            try:
                                if sample.general.referencegenus == 'Listeria':
                                    additional_fields.append('PredictedSerogroup')
                            except AttributeError:
                                pass
                            header_fields = additional_fields
                        else:
                            additional_fields = [
                                'genus', 'species', 'subspecies', 'lineage', 'sublineage', 'other_designation', 'notes'
                            ]
                            header_fields = [
                                'rMLST_genus', 'species', 'subspecies', 'lineage', 'sublineage', 'other_designation',
                                'notes'
                            ]
                        # Populate the header with the appropriate data, including all the genes in the list of targets
                        if not header_row:
                            if additional_fields:
                                header_row = 'Strain,MASHGenus,{additional},SequenceType,Matches,{matches},\n' \
                                    .format(additional=','.join(header_fields),
                                            matches=','.join(sorted(sample[self.analysistype].allelenames)))
                            else:
                                header_row = 'Strain,MASHGenus,SequenceType,Matches,{matches},\n' \
                                    .format(matches=','.join(sorted(sample[self.analysistype].allelenames)))
                        # Iterate through the best sequence types for the sample
                        for seqtype in self.resultprofile[sample.name]:
                            sample[self.analysistype].sequencetype = seqtype
                            try:
                                if sample.general.referencegenus == 'Listeria':
                                    for serogroup, mlst_list in self.listeria_serogroup_dict.items():
                                        if seqtype in [str(string) for string in mlst_list]:
                                            sample[self.analysistype].meta_dict[seqtype]['PredictedSerogroup'] = \
                                                serogroup
                            except AttributeError:
                                pass
                            # The number of matches to the profile
                            sample[self.analysistype].matches = list(self.resultprofile[sample.name][seqtype].keys())[0]
                            # Extract the closest reference genus
                            try:
                                genus = sample.general.referencegenus
                            except AttributeError:
                                try:
                                    genus = sample.general.closestrefseqgenus
                                except AttributeError:
                                    genus = 'ND'
                            # If this is the first of one or more sequence types, include the sample name
                            if additional_fields:
                                row += '{name},{mashgenus},{additional},{seqtype},{matches},'\
                                    .format(name=sample.name,
                                            mashgenus=genus,
                                            additional=','.join(sample[self.analysistype].
                                                                meta_dict[sample[self.analysistype]
                                                                .sequencetype][header] for header in additional_fields),
                                            seqtype=seqtype,
                                            matches=sample[self.analysistype].matches)
                            else:
                                row += '{name},{mashgenus},{seqtype},{matches},' \
                                    .format(name=sample.name,
                                            mashgenus=genus,
                                            seqtype=seqtype,
                                            matches=sample[self.analysistype].matches)
                            # Iterate through all the genes present in the analyses for the sample
                            for gene in sorted(sample[self.analysistype].allelenames):
                                refallele = sample[self.analysistype].profiledata[seqtype][gene]
                                # Set the allele and percent id from the dictionary's keys and values, respectively
                                allele = \
                                    list(self.resultprofile[sample.name][seqtype][sample[self.analysistype].matches]
                                         [gene].keys())[0]
                                percentid = \
                                    list(self.resultprofile[sample.name][seqtype][sample[self.analysistype].matches]
                                         [gene].values())[0]
                                try:
                                    if refallele and refallele != allele:
                                        if 0 < float(percentid) < 100:
                                            row += '{} ({:.2f}%),'.format(allele, float(percentid))
                                        else:
                                            row += '{} ({}),'.format(allele, refallele)
                                    else:
                                        # Add the allele and % id to the row (only add the % identity if it is not 100%)
                                        if 0 < float(percentid) < 100:
                                            row += '{} ({:.2f}%),'.format(allele, float(percentid))
                                        else:
                                            row += '{},'.format(allele)
                                    self.referenceprofile[sample.name][gene] = allele
                                except ValueError:
                                    pass
                            # Add a newline
                            row += '\n'
                        #
                        combinedrow += row
                        #
                        combined_header_row += header_row
                        combined_header_row += row
                        if self.analysistype == 'mlst':
                            mlst_dict[sample.general.referencegenus]['header'] = header_row
                            try:
                                mlst_dict[sample.general.referencegenus]['combined_row'] += row
                            except KeyError:
                                mlst_dict[sample.general.referencegenus]['combined_row'] = str()
                                mlst_dict[sample.general.referencegenus]['combined_row'] += row
                        # If the length of the # of report directories is greater than 1 (script is being run as part of
                        # the assembly pipeline) make a report for each sample
                        if self.pipeline:
                            # Open the report
                            with open(os.path.join(sample[self.analysistype].reportdir,
                                                   '{}_{}.csv'.format(sample.name, self.analysistype)), 'w') as report:
                                # Write the row to the report
                                report.write(header_row)
                                report.write(row)
        # Create the report folder
        make_path(self.reportpath)
        # Create the report containing all the data from all samples
        if self.analysistype == 'mlst':
            for genus in mlst_dict:
                if mlst_dict[genus]['combined_row']:
                    with open(os.path.join(self.reportpath, '{at}_{genus}.csv'.format(at=self.analysistype,
                                                                                      genus=genus)), 'w') \
                            as mlstreport:
                        # Add the header
                        mlstreport.write(mlst_dict[genus]['header'])
                        # Write the results to this report
                        mlstreport.write(mlst_dict[genus]['combined_row'])
            with open(os.path.join(self.reportpath,  '{at}.csv'.format(at=self.analysistype)), 'w') \
                    as combinedreport:
                # Write the results to this report
                combinedreport.write(combined_header_row)
        else:
            with open(os.path.join(self.reportpath,  '{at}.csv'.format(at=self.analysistype)), 'w') \
                    as combinedreport:
                # Add the header
                combinedreport.write(header_row)
                # Write the results to this report
                combinedreport.write(combinedrow)
1299051
def reporter(self):
        
        # Create the path in which the reports are stored
        make_path(self.reportpath)
        header = 'Strain,Gene,PercentIdentity,Genus,FoldCoverage\n'
        data = ''
        with open(os.path.join(self.reportpath, self.analysistype + '.csv'), 'w') as report:
            for sample in self.runmetadata.samples:
                data += sample.name + ','
                if sample[self.analysistype].results:
                    if not sample[self.analysistype].multiple:
                        for name, identity in sample[self.analysistype].results.items():
                            if name == sample[self.analysistype].besthit[0]:
                                data += '{},{},{},{}\n'.format(name, identity, sample[self.analysistype].genera[name],
                                                               sample[self.analysistype].avgdepth[name])
                    else:
                        data += '{},{},{},{}\n'.format('multiple', 'NA', ';'.join(sample[self.analysistype]
                                                                                  .classification), 'NA')
                else:
                    data += '\n'
            report.write(header)
            report.write(data)
700874
protected Scan createScanner(Configuration parameters) {
		Scan scan = null;
		if (parameters.getString(SCAN, null) != null) {
			try {
				scan = HBaseUtil.convertStringToScan(parameters.getString(SCAN, null));
			} catch (IOException e) {
				LOG.error("An error occurred.", e);
			}
		} else {
			try {
				scan = new Scan();

				// if (parameters.getString(SCAN_COLUMNS, null) != null) {
				// scan.addColumns(parameters.getString(SCAN_COLUMNS, null));
				// }

				if (parameters.getString(SCAN_COLUMN_FAMILY, null) != null) {
					scan.addFamily(Bytes.toBytes(parameters.getString(SCAN_COLUMN_FAMILY, null)));
				}

				if (parameters.getString(SCAN_TIMESTAMP, null) != null) {
					scan.setTimeStamp(Long.parseLong(parameters.getString(SCAN_TIMESTAMP, null)));
				}

				if (parameters.getString(SCAN_TIMERANGE_START, null) != null
					&& parameters.getString(SCAN_TIMERANGE_END, null) != null) {
					scan.setTimeRange(
						Long.parseLong(parameters.getString(SCAN_TIMERANGE_START, null)),
						Long.parseLong(parameters.getString(SCAN_TIMERANGE_END, null)));
				}

				if (parameters.getString(SCAN_MAXVERSIONS, null) != null) {
					scan.setMaxVersions(Integer.parseInt(parameters.getString(SCAN_MAXVERSIONS, null)));
				}

				if (parameters.getString(SCAN_CACHEDROWS, null) != null) {
					scan.setCaching(Integer.parseInt(parameters.getString(SCAN_CACHEDROWS, null)));
				}

				// false by default, full table scans generate too much BC churn
				scan.setCacheBlocks((parameters.getBoolean(SCAN_CACHEBLOCKS, false)));
			} catch (Exception e) {
				LOG.error(StringUtils.stringifyException(e));
			}
		}
		return scan;
	}
133416
def reporter(self):
        
        # Create the path in which the reports are stored
        make_path(self.reportpath)
        logging.info('Creating {} report'.format(self.analysistype))
        # Initialise the header and data strings
        header = 'Strain,Gene,PercentIdentity,Genus,FoldCoverage\n'
        data = ''
        with open(self.sixteens_report, 'w') as report:
            with open(os.path.join(self.reportpath, self.analysistype + '_sequences.fa'), 'w') as sequences:
                for sample in self.runmetadata.samples:
                    # Initialise
                    sample[self.analysistype].sixteens_match = 'NA'
                    sample[self.analysistype].species = 'NA'
                    try:
                        # Select the best hit of all the full-length 16S genes mapped - for 16S use the hit with the
                        # fewest number of SNPs rather than the highest percent identity
                        sample[self.analysistype].besthit = sorted(sample[self.analysistype].resultssnp.items(),
                                                                   key=operator.itemgetter(1))[0][0]
                        # Parse the baited FASTA file to pull out the the description of the hit
                        for record in SeqIO.parse(sample[self.analysistype].baitfile, 'fasta'):
                            # If the best hit e.g. gi|631251361|ref|NR_112558.1| is present in the current record,
                            # gi|631251361|ref|NR_112558.1| Escherichia coli strain JCM 1649 16S ribosomal RNA ...,
                            # extract the match and the species
                            if sample[self.analysistype].besthit in record.id:
                                # Set the best match and species from the records
                                sample[self.analysistype].sixteens_match = record.description.split(' 16S')[0]
                                sample[self.analysistype].species = \
                                    sample[self.analysistype].sixteens_match.split('|')[-1].split()[1]
                        # Add the sample name to the data string
                        data += sample.name + ','
                        # Find the record that matches the best hit, and extract the necessary values to be place in the
                        # data string
                        for name, identity in sample[self.analysistype].results.items():
                            if name == sample[self.analysistype].besthit:
                                data += '{},{},{},{}\n'.format(name, identity, sample[self.analysistype].genus,
                                                               sample[self.analysistype].avgdepth[name])
                                # Create a FASTA-formatted sequence output of the 16S sequence
                                record = SeqRecord(Seq(sample[self.analysistype].sequences[name],
                                                       IUPAC.unambiguous_dna),
                                                   id='{}_{}'.format(sample.name, '16S'),
                                                   description='')
                                SeqIO.write(record, sequences, 'fasta')
                    except (AttributeError, IndexError):
                        data += '{}\n'.format(sample.name)
            # Write the results to the report
            report.write(header)
            report.write(data)