001/* 002 * BioJava development code 003 * 004 * This code may be freely distributed and modified under the 005 * terms of the GNU Lesser General Public Licence. This should 006 * be distributed with the code. If you do not have a copy, 007 * see: 008 * 009 * http://www.gnu.org/copyleft/lesser.html 010 * 011 * Copyright for this code is held jointly by the individual 012 * authors. These should be listed in @author doc comments. 013 * 014 * For more information on the BioJava project and its aims, 015 * or to join the biojava-l mailing list, visit the home page 016 * at: 017 * 018 * http://www.biojava.org/ 019 * 020 */ 021package org.biojava.bio.program.fastq; 022 023import java.util.HashMap; 024import java.util.Map; 025 026/** 027 * FASTQ sequence format variant. 028 * 029 * @since 1.7.1 030 */ 031public enum FastqVariant 032{ 033 /** Sanger FASTQ sequence format variant. */ 034 FASTQ_SANGER("Original or Sanger format") 035 { 036 @Override 037 public int minimumQualityScore() 038 { 039 return 0; 040 } 041 042 @Override 043 public int maximumQualityScore() 044 { 045 return 93; 046 } 047 048 @Override 049 public int qualityScore(final char c) 050 { 051 return ((int) c) - 33; 052 } 053 054 @Override 055 public char quality(final int qualityScore) 056 { 057 if (qualityScore < minimumQualityScore()) 058 { 059 throw new IllegalArgumentException("qualityScore must be greater than or equal to minimumQualityScore()"); 060 } 061 if (qualityScore > maximumQualityScore()) 062 { 063 throw new IllegalArgumentException("qualityScore must be less than or equal to maximumQualityScore()"); 064 } 065 return (char) (qualityScore + 33); 066 } 067 068 @Override 069 public double errorProbability(final int qualityScore) 070 { 071 return Math.pow(10.0d, ((double) qualityScore) / -10.0d); 072 } 073 }, 074 075 /** Solexa FASTQ sequence format variant. */ 076 FASTQ_SOLEXA("Solexa and early Illumina format") 077 { 078 @Override 079 public int minimumQualityScore() 080 { 081 return -5; 082 } 083 084 @Override 085 public int maximumQualityScore() 086 { 087 return 62; 088 } 089 090 @Override 091 public int qualityScore(final char c) 092 { 093 return ((int) c) - 64; 094 } 095 096 @Override 097 public char quality(final int qualityScore) 098 { 099 if (qualityScore < minimumQualityScore()) 100 { 101 throw new IllegalArgumentException("qualityScore must be greater than or equal to minimumQualityScore()"); 102 } 103 if (qualityScore > maximumQualityScore()) 104 { 105 throw new IllegalArgumentException("qualityScore must be less than or equal to maximumQualityScore()"); 106 } 107 return (char) (qualityScore + 64); 108 } 109 110 @Override 111 public double errorProbability(final int qualityScore) 112 { 113 double q = Math.pow(10.0d, ((double) qualityScore) / -10.0d); 114 return q / (1 + q); 115 } 116 }, 117 118 /** Illumina FASTQ sequence format variant. */ 119 FASTQ_ILLUMINA("Illumina 1.3+ format") 120 { 121 @Override 122 public int minimumQualityScore() 123 { 124 return 0; 125 } 126 127 @Override 128 public int maximumQualityScore() 129 { 130 return 62; 131 } 132 133 @Override 134 public int qualityScore(final char c) 135 { 136 return ((int) c) - 64; 137 } 138 139 @Override 140 public char quality(final int qualityScore) 141 { 142 if (qualityScore < minimumQualityScore()) 143 { 144 throw new IllegalArgumentException("qualityScore must be greater than or equal to minimumQualityScore()"); 145 } 146 if (qualityScore > maximumQualityScore()) 147 { 148 throw new IllegalArgumentException("qualityScore must be less than or equal to maximumQualityScore()"); 149 } 150 return (char) (qualityScore + 64); 151 } 152 153 @Override 154 public double errorProbability(final int qualityScore) 155 { 156 return Math.pow(10.0d, ((double) qualityScore) / -10.0d); 157 } 158 }; 159 160 161 /** Map of FASTQ sequence format variants keyed by name and lowercase-with-dashes name. */ 162 private static final Map<String, FastqVariant> FASTQ_VARIANTS = new HashMap<String, FastqVariant>(6); 163 164 static 165 { 166 for (FastqVariant fastqVariant : values()) 167 { 168 FASTQ_VARIANTS.put(fastqVariant.name(), fastqVariant); 169 FASTQ_VARIANTS.put(fastqVariant.lowercaseName(), fastqVariant); 170 } 171 } 172 173 /** Description of this FASTQ sequence format variant. */ 174 private final String description; 175 176 177 /** 178 * Create a new FASTQ sequence format variant with the specified description. 179 * 180 * @param description description of this FASTQ sequence format variant, must not be null 181 */ 182 private FastqVariant(final String description) 183 { 184 if (description == null) 185 { 186 throw new IllegalArgumentException("description must not be null"); 187 } 188 this.description = description; 189 } 190 191 192 /** 193 * Return the description of this FASTQ sequence format variant. 194 * The description will not be null. 195 * 196 * @return the description of this FASTQ sequence format variant 197 */ 198 public String getDescription() 199 { 200 return description; 201 } 202 203 /** 204 * Return true if this FASTQ sequence format variant is {@link #FASTQ_SANGER}. 205 * 206 * @return true if this FASTQ sequence format variant is {@link #FASTQ_SANGER} 207 */ 208 public boolean isSanger() 209 { 210 return (this == FASTQ_SANGER); 211 } 212 213 /** 214 * Return true if this FASTQ sequence format variant is {@link #FASTQ_SOLEXA}. 215 * 216 * @return true if this FASTQ sequence format variant is {@link #FASTQ_SOLEXA} 217 */ 218 public boolean isSolexa() 219 { 220 return (this == FASTQ_SOLEXA); 221 } 222 223 /** 224 * Return true if this FASTQ sequence format variant is {@link #FASTQ_ILLUMINA}. 225 * 226 * @return true if this FASTQ sequence format variant is {@link #FASTQ_ILLUMINA} 227 */ 228 public boolean isIllumina() 229 { 230 return (this == FASTQ_ILLUMINA); 231 } 232 233 /** 234 * Return the minimum quality score for this FASTQ sequence format variant. 235 * 236 * @since 1.8.2 237 * @return the minimum quality score for this FASTQ sequence format variant. 238 */ 239 public abstract int minimumQualityScore(); 240 241 /** 242 * Return the maximum quality score for this FASTQ sequence format variant. 243 * 244 * @since 1.8.2 245 * @return the maximum quality score for this FASTQ sequence format variant. 246 */ 247 public abstract int maximumQualityScore(); 248 249 /** 250 * Convert the specified quality in ASCII format to a quality score. 251 * 252 * @since 1.8.2 253 * @param c quality in ASCII format 254 * @return the specified quality in ASCII format converted to a quality score 255 */ 256 public abstract int qualityScore(char c); 257 258 /** 259 * Convert the specified quality score to a quality in ASCII format. 260 * 261 * @since 1.8.3 262 * @param qualityScore quality score, must be <code>>= minimumQualityScore()</code> 263 * and <code><= maximumQualityScore()</code> 264 * @return the quality in ASCII format converted from the specified quality score 265 */ 266 public abstract char quality(int qualityScore); 267 268 /** 269 * Convert the specified quality in ASCII format to an error probability. 270 * 271 * @since 1.8.2 272 * @param c quality in ASCII format 273 * @return the specified quality in ASCII format converted to an error probability 274 */ 275 public double errorProbability(char c) 276 { 277 return errorProbability(qualityScore(c)); 278 } 279 280 /** 281 * Calculate the error probability given the specified quality score. 282 * 283 * @since 1.8.2 284 * @param qualityScore quality score 285 * @return the error probability given the specified quality score 286 */ 287 public abstract double errorProbability(int qualityScore); 288 289 /** 290 * Return the name of this FASTQ sequence format variant in <code>lowercase-with-dashes</code> style. 291 * 292 * @return the name of this FASTQ sequence format variant in <code>lowercase-with-dashes</code> style 293 */ 294 public String lowercaseName() 295 { 296 return name().toLowerCase().replace('_', '-'); 297 } 298 299 300 /** 301 * Return the FASTQ sequence format variant with the specified name, if any. The name may 302 * be specified in either <code>UPPERCASE_WITH_UNDERSCORES</code> 303 * or <code>lowercase-with-dashes</code> style. 304 * 305 * @param name name 306 * @return the FASTQ sequence format variant with the specified name, or <code>null</code> 307 * if no such FASTQ sequence format variant exists 308 */ 309 public static FastqVariant parseFastqVariant(final String name) 310 { 311 return FASTQ_VARIANTS.get(name); 312 } 313}