/* * The MIT License * * Copyright (c) 2009 The Broad Institute * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package htsjdk.samtools; /** * Class that encapsulates a validation error message as well as a type code so that * errors can be aggregated by type. * * @author Doug Voet */ public class SAMValidationError { public enum Severity { WARNING, ERROR } public enum Type { /** quality encodings out of range; appear to be Solexa or Illumina when Phread expected */ INVALID_QUALITY_FORMAT(Severity.WARNING), /** proper pair flag set for unpaired read */ INVALID_FLAG_PROPER_PAIR, /** mate unmapped flag set when mate is mapped or not set when mate is not mapped */ INVALID_FLAG_MATE_UNMAPPED, /** mate unmapped flag does not match read unmapped flag of mate */ MISMATCH_FLAG_MATE_UNMAPPED, /** mate negative strand flag set for unpaired read */ INVALID_FLAG_MATE_NEG_STRAND, /** mate negative strand flag does not match read negative strand flag of mate */ MISMATCH_FLAG_MATE_NEG_STRAND, /** first of pair flag set for unpaired read */ INVALID_FLAG_FIRST_OF_PAIR, /** second of pair flag set for unpaired read */ INVALID_FLAG_SECOND_OF_PAIR, /** pair flag set but not marked as first or second of pair */ PAIRED_READ_NOT_MARKED_AS_FIRST_OR_SECOND(Severity.WARNING), /** not primary alignment flag set for unmapped read */ INVALID_FLAG_NOT_PRIM_ALIGNMENT, /** supplementary alignment flag set for unmapped read */ INVALID_FLAG_SUPPLEMENTARY_ALIGNMENT, /** mapped read flat not set for mapped read */ INVALID_FLAG_READ_UNMAPPED, /** * inferred insert size is out of range * @see SAMRecord#MAX_INSERT_SIZE */ INVALID_INSERT_SIZE, /** mapping quality set for unmapped read or is >= 256 */ INVALID_MAPPING_QUALITY, /** CIGAR string is empty for mapped read or not empty of unmapped read, or other CIGAR badness. */ INVALID_CIGAR, /** CIGAR string contains I followed by D, or vice versa */ ADJACENT_INDEL_IN_CIGAR(Severity.WARNING), /** mate reference index (MRNM) set for unpaired read */ INVALID_MATE_REF_INDEX, /** mate reference index (MRNM) does not match reference index of mate */ MISMATCH_MATE_REF_INDEX, /** reference index not found in sequence dictionary */ INVALID_REFERENCE_INDEX, /** alignment start is can not be correct */ INVALID_ALIGNMENT_START, /** mate alignment does not match alignment start of mate */ MISMATCH_MATE_ALIGNMENT_START, /** the record's mate fields do not match the corresponding fields of the mate */ MATE_FIELD_MISMATCH, /** the NM tag (nucleotide differences) is incorrect */ INVALID_TAG_NM, /** the NM tag (nucleotide differences) is missing */ MISSING_TAG_NM(Severity.WARNING), /** the sam/bam file is missing the header */ MISSING_HEADER, /** there is no sequence dictionary in the header */ MISSING_SEQUENCE_DICTIONARY, /** the header is missing read group information */ MISSING_READ_GROUP, /** the record is out of order */ RECORD_OUT_OF_ORDER, /** A read group ID on a SAMRecord is not found in the header */ READ_GROUP_NOT_FOUND, /** A SAMRecord is found with no read group id */ RECORD_MISSING_READ_GROUP(Severity.WARNING), /** Indexing bin set on SAMRecord does not agree with computed value. */ INVALID_INDEXING_BIN, MISSING_VERSION_NUMBER, INVALID_VERSION_NUMBER, TRUNCATED_FILE, MISMATCH_READ_LENGTH_AND_QUALS_LENGTH, EMPTY_READ, /** * Bases corresponding to M operator in CIGAR are beyond the end of the reference. */ CIGAR_MAPS_OFF_REFERENCE, /** Length of E2 (secondary base calls) and U2 (secondary base quals) tag values should match read length */ MISMATCH_READ_LENGTH_AND_E2_LENGTH, MISMATCH_READ_LENGTH_AND_U2_LENGTH, /** Secondary base calls should not be the same as primary, unless one or the other is N */ E2_BASE_EQUALS_PRIMARY_BASE(Severity.WARNING), /** BAM appears to be healthy, but is an older file so doesn't have terminator block. */ BAM_FILE_MISSING_TERMINATOR_BLOCK(Severity.WARNING), /** Header record is not one of the standard types */ UNRECOGNIZED_HEADER_TYPE, /** Header tag does not have colon */ POORLY_FORMATTED_HEADER_TAG, /** Header tag appears more than once in header line with different value */ HEADER_TAG_MULTIPLY_DEFINED, HEADER_RECORD_MISSING_REQUIRED_TAG, /** Date string is not ISO-8601 */ INVALID_DATE_STRING(Severity.WARNING), /** Unsigned integer tag value is deprecated in BAM. */ TAG_VALUE_TOO_LARGE, /** Invalid virtualFilePointer in index */ INVALID_INDEX_FILE_POINTER, /** PI tag value is not numeric. */ INVALID_PREDICTED_MEDIAN_INSERT_SIZE, /** Same read group id appears more than once */ DUPLICATE_READ_GROUP_ID, /** The read group is missing its PL (platform unit) field */ MISSING_PLATFORM_VALUE, /** The read group has an invalid value set for its PL field */ INVALID_PLATFORM_VALUE, /** Same program group id appears more than once */ DUPLICATE_PROGRAM_GROUP_ID, /** Read is marked as paired, but its pair was not found. */ MATE_NOT_FOUND, /** Both mates are marked as first of pair, or both mates are marked as second of pair. */ MATES_ARE_SAME_END, /** The Cigar String in the MC Tag does not match the Cigar String for the mate of this read. */ MISMATCH_MATE_CIGAR_STRING, /** There is a Cigar String (stored in the MC Tag) for a read whose mate is NOT mapped. */ MATE_CIGAR_STRING_INVALID_PRESENCE; public final Severity severity; private Type() { this.severity = Severity.ERROR; } private Type(final Severity severity) { this.severity = severity; } /** * @return Format for writing to histogram summary output. */ public String getHistogramString() { return this.severity.name() + ":" + this.name(); } } private final Type type; private final String message; private final String readName; private long recordNumber = -1; private String source; /** * Construct a SAMValidationError with unknown record number. * @param type * @param message * @param readName May be null if readName is not known. */ public SAMValidationError(final Type type, final String message, final String readName) { this.type = type; this.message = message; this.readName = readName; } /** * Construct a SAMValidationError with possibly-known record number. * @param type * @param message * @param readName May be null if readName is not known. * @param recordNumber Position of the record in the SAM file it has been read from. -1 if not known. */ public SAMValidationError(final Type type, final String message, final String readName, final long recordNumber) { this(type, message, readName); this.recordNumber = recordNumber; } public String toString() { final StringBuilder builder = new StringBuilder(); builder.append(type.severity.toString()); builder.append(": "); if (source != null) { builder.append("File ").append(source.toString()).append(", "); } if (recordNumber > 0) { builder.append("Record ").append(recordNumber).append(", "); } if (readName != null) { builder.append("Read name ").append(readName).append(", "); } return builder.append(message).toString(); } public Type getType() { return type; } public String getMessage() { return message; } /** may be null */ public String getReadName() { return readName; } /** 1-based. -1 if not known. */ public long getRecordNumber() { return recordNumber; } public void setRecordNumber(final long recordNumber) { this.recordNumber = recordNumber; } public String getSource() { return source; } public void setSource(final String source) { this.source = source; } }