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 * Created on 2011-11-20 021 * 022 */ 023 024package org.biojava.nbio.ws.alignment.qblast; 025 026import org.biojava.nbio.ws.alignment.RemotePairwiseAlignmentProperties; 027 028import java.util.HashMap; 029import java.util.HashSet; 030import java.util.Map; 031import java.util.Set; 032 033import static org.biojava.nbio.ws.alignment.qblast.BlastAlignmentParameterEnum.*; 034 035/** 036 * This class wraps a QBlast search request parameter {@code Map} by adding several convenient parameter addition 037 * methods. Other QBlast URL API parameters should be added using 038 * {@link #setAlignmentOption(BlastAlignmentParameterEnum, String)} 039 * <p/> 040 * Required parameters are {@code PROGRAM} and {@code DATABASE}, other parameters are optional 041 * 042 * @author Sylvain Foisy, Diploide BioIT 043 * @author Gediminas Rimsa 044 */ 045public class NCBIQBlastAlignmentProperties implements RemotePairwiseAlignmentProperties { 046 private static final long serialVersionUID = 7158270364392309841L; 047 048 private Map<BlastAlignmentParameterEnum, String> param = new HashMap<BlastAlignmentParameterEnum, String>(); 049 050 /** 051 * This method forwards to {@link #getAlignmentOption(BlastAlignmentParameterEnum)}. Consider using it instead. 052 */ 053 @Override 054 public String getAlignmentOption(String key) { 055 return getAlignmentOption(BlastAlignmentParameterEnum.valueOf(key)); 056 } 057 058 /** 059 * This method forwards to {@link #setAlignmentOption(BlastAlignmentParameterEnum, String)}. Consider using it 060 * instead. 061 */ 062 @Override 063 public void setAlignementOption(String key, String val) { 064 setAlignmentOption(BlastAlignmentParameterEnum.valueOf(key), val); 065 } 066 067 /** 068 * Gets parameters, which are currently set 069 */ 070 @Override 071 public Set<String> getAlignmentOptions() { 072 Set<String> result = new HashSet<String>(); 073 for (BlastAlignmentParameterEnum parameter : param.keySet()) { 074 result.add(parameter.name()); 075 } 076 return result; 077 } 078 079 /** 080 * Gets the value of specified parameter or {@code null} if it is not set. 081 */ 082 public String getAlignmentOption(BlastAlignmentParameterEnum key) { 083 return param.get(key); 084 } 085 086 /** 087 * Sets the value of specified parameter 088 */ 089 public void setAlignmentOption(BlastAlignmentParameterEnum key, String val) { 090 param.put(key, val); 091 } 092 093 /** 094 * Removes given parameter 095 */ 096 public void removeAlignmentOption(BlastAlignmentParameterEnum key) { 097 param.remove(key); 098 } 099 100 /** 101 * @return {@linkplain BlastProgramEnum} used for blast run 102 */ 103 public BlastProgramEnum getBlastProgram() { 104 BlastProgramEnum program = BlastProgramEnum.valueOf(getAlignmentOption(PROGRAM)); 105 boolean isMegablast = BlastProgramEnum.blastn == program && getAlignmentOption(MEGABLAST).equals("on"); 106 return !isMegablast ? program : BlastProgramEnum.megablast; 107 } 108 109 /** 110 * Sets the program to be used with blastall 111 * 112 * @param program : one of blastall programs 113 */ 114 public void setBlastProgram(BlastProgramEnum program) { 115 if (BlastProgramEnum.megablast != program) { 116 setAlignmentOption(PROGRAM, program.name()); 117 removeAlignmentOption(MEGABLAST); 118 } else { 119 setAlignmentOption(PROGRAM, BlastProgramEnum.blastn.name()); 120 setAlignmentOption(MEGABLAST, "on"); 121 } 122 } 123 124 /** 125 * @return name of database used with blastall 126 */ 127 public String getBlastDatabase() { 128 return getAlignmentOption(DATABASE); 129 } 130 131 /* 132 * TODO: update comment when URL is available: 133 * A quite exhaustive list of the databases available for QBlast 134 * requests can be found here: <p> http://< to_be_completed > <p> Blastall equivalent: -d 135 */ 136 137 /** 138 * Sets the database to be used with blastall 139 * <p> 140 * A list of available databases can be acquired by calling {@link NCBIQBlastService#printRemoteBlastInfo()} 141 * <p> 142 * Blastall equivalent: -d 143 * 144 * @param db : a valid name to a NCBI blastable database 145 */ 146 public void setBlastDatabase(String database) { 147 setAlignmentOption(DATABASE, database); 148 } 149 150 /** 151 * @return double value of EXPECT parameter used for blast run 152 */ 153 public double getBlastExpect() { 154 if (param.containsKey(EXPECT)) { 155 return Double.parseDouble(getAlignmentOption(EXPECT)); 156 } 157 return 10; 158 } 159 160 /** 161 * Sets the EXPECT parameter to be use with blastall 162 * <p> 163 * Example: if you want a EXPECT of 1e-10, pass {@code Double.parseDouble("1e-10")} as a parameter 164 * <p> 165 * Blastall equivalent: -e 166 * 167 * @param expect: a double value of EXPECT parameter 168 */ 169 public void setBlastExpect(double expect) { 170 setAlignmentOption(EXPECT, Double.toString(expect)); 171 } 172 173 /** 174 * Returns the value of the WORD_SIZE parameter used for this blast run 175 * 176 * @return int value of WORD_SIZE used by this search 177 * @throws IllegalArgumentException when program type is not set and program type is not supported 178 */ 179 public int getBlastWordSize() { 180 if (param.containsKey(WORD_SIZE)) { 181 return Integer.parseInt(getAlignmentOption(WORD_SIZE)); 182 } 183 184 // return default word size value 185 try { 186 BlastProgramEnum programType = getBlastProgram(); 187 switch (programType) { 188 case blastn: 189 return 11; 190 case megablast: 191 return 28; 192 case blastp: 193 case blastx: 194 case tblastn: 195 case tblastx: 196 return 3; 197 default: 198 throw new UnsupportedOperationException("Blast program " + programType.name() + " is not supported."); 199 } 200 } catch (IllegalArgumentException e) { 201 throw new IllegalArgumentException("Blast program " + getBlastProgram() + " is not supported.", e); 202 } 203 } 204 205 /** 206 * Sets the WORD_SIZE parameter to be use with blastall 207 * <p> 208 * <b>WARNING!!</b> At this point, the method does not verify the validity of your choice; for example, word size of 209 * greater than 5 with blastp returns error messages from QBlast. Word size range depends on the algorithm chosen. 210 * <p> 211 * More at https://www.ncbi.nlm.nih.gov/staff/tao/URLAPI/new/node74.html 212 * <p> 213 * Blastall equivalent: -W 214 * 215 * @param word: an int used to set WORD_SIZE 216 */ 217 public void setBlastWordSize(int word) { 218 setAlignmentOption(WORD_SIZE, Integer.toString(word)); 219 } 220 221 /** 222 * Returns the value for the GAP_CREATION parameter (first half of GAPCOSTS parameter) 223 * 224 * @return an integer value for gap creation used by this search, -1 if not set or not a number 225 */ 226 public int getBlastGapCreation() { 227 String gapCosts = getAlignmentOption(GAPCOSTS); 228 try { 229 String gapCreation = gapCosts.split("\\+")[0]; 230 return Integer.parseInt(gapCreation); 231 } catch (Exception e) { 232 return -1; 233 } 234 } 235 236 /** 237 * Returns the value for the gap extension parameter (second half of GAPCOSTS parameter) 238 * 239 * @return an integer for the value for gap extension used by this search, -1 if not set or not a number 240 */ 241 public int getBlastGapExtension() { 242 String gapCosts = getAlignmentOption(GAPCOSTS); 243 try { 244 String gapExtension = gapCosts.split("\\+")[1]; 245 return Integer.parseInt(gapExtension); 246 } catch (Exception e) { 247 return -1; 248 } 249 } 250 251 /** 252 * Returns the actual string for the GAPCOSTS parameter which is used to build the URL 253 * 254 * @return the string representation of the GAPCOSTS parameter formatted for the URL 255 */ 256 public String getBlastGapCosts() { 257 return getAlignmentOption(GAPCOSTS); 258 } 259 260 /** 261 * Sets the GAPCOSTS parameter 262 * 263 * @param gapCreation integer to use as gap creation value 264 * @param gapExtension integer to use as gap extension value 265 */ 266 public void setBlastGapCosts(int gapCreation, int gapExtension) { 267 String gc = Integer.toString(gapCreation); 268 String ge = Integer.toString(gapExtension); 269 setAlignmentOption(GAPCOSTS, gc + "+" + ge); 270 } 271 272 /** 273 * Returns the value of the specified substitution matrix 274 * 275 * @return matrix: the name of the specified substitution matrix 276 */ 277 public String getBlastMatrix() { 278 return getAlignmentOption(MATRIX_NAME); 279 } 280 281 /** 282 * Sets the value for the MATRIX parameter to use for blastall 283 * <p> 284 * Blastall equivalent: -M 285 * 286 * @param matrix : a String to use as gap creation value 287 * @see BlastMatrixEnum 288 */ 289 public void setBlastMatrix(BlastMatrixEnum matrix) { 290 setAlignmentOption(MATRIX_NAME, matrix.name()); 291 292 boolean gapCostsSet = getBlastGapCreation() != -1 || getBlastGapExtension() != -1; 293 294 if (!gapCostsSet) { 295 /* 296 * Setting default values for -G/-E if no other values have been set is necessary because, since BLOSUM62 is 297 * default, the expected values are -G 11 -E 1. If your matrix choice is different, the request will fail, 298 * implicitly expecting GAPCOSTS=11+1 299 */ 300 switch (matrix) { 301 case PAM30: 302 setBlastGapCosts(9, 1); 303 break; 304 case PAM70: 305 setBlastGapCosts(10, 1); 306 break; 307 case PAM250: 308 setBlastGapCosts(14, 2); 309 break; 310 case BLOSUM45: 311 setBlastGapCosts(15, 2); 312 break; 313 case BLOSUM50: 314 setBlastGapCosts(13, 2); 315 break; 316 case BLOSUM80: 317 case BLOSUM90: 318 setBlastGapCosts(10, 1); 319 break; 320 case BLOSUM62: 321 break; 322 default: 323 break; 324 } 325 } 326 } 327 328 /** 329 * Sets the QUERY_FROM and QUERY_TO parameters to be use by blast. Do not use if you want to use the whole sequence.<br/> 330 * Blastall equivalent: -L 331 * 332 * @param start QUERY_FROM parameter 333 * @param end QUERY_TO parameter 334 */ 335 public void setBlastFromToPosition(int start, int end) { 336 if (start >= end) { 337 throw new IllegalArgumentException("Start index must be less than end index"); 338 } 339 setAlignmentOption(QUERY_FROM, String.valueOf(start)); 340 setAlignmentOption(QUERY_TO, String.valueOf(end)); 341 } 342 343 /** 344 * @return an integer value for the QUERY_FROM parameter 345 * @see #setBlastFromToPosition(int, int) 346 */ 347 public int getBlastFromPosition() { 348 return Integer.parseInt(getAlignmentOption(QUERY_FROM)); 349 } 350 351 /** 352 * @return QUERY_TO parameter 353 * @see #setBlastFromToPosition(int, int) 354 */ 355 public int getBlastToPosition() { 356 return Integer.parseInt(getAlignmentOption(QUERY_TO)); 357 } 358 359 /** 360 * This method is to be used if a request is to use non-default values at submission. Useful for the following 361 * blastall parameters: 362 * <ul> 363 * <li>-r: integer to reward for match. Default = 1</li> 364 * <li>-q: negative integer for penalty to allow mismatch. Default = -3</li> 365 * <li>-y: dropoff for blast extensions in bits, using default if not specified. Default = 20 for blastn, 7 for all 366 * others (except megablast for which it is not applicable).</li> 367 * <li>-X: X dropoff value for gapped alignment, in bits. Default = 30 for blastn/megablast, 15 for all others.</li> 368 * <li>-Z: final X dropoff value for gapped alignement, in bits. Default = 50 for blastn, 25 for all others (except 369 * megablast for which it is not applicable)</li> 370 * <li>-P: equals 0 for multiple hits 1-pass, 1 for single hit 1-pass. Does not apply to blastn ou megablast.</li> 371 * <li>-A: multiple hits window size. Default = 0 (for single hit algorithm)</li> 372 * <li>-I: number of database sequences to save hits for. Default = 500</li> 373 * <li>-Y: effective length of the search space. Default = 0 (0 represents using the whole space)</li> 374 * <li>-z: a real specifying the effective length of the database to use. Default = 0 (0 represents the real size)</li> 375 * <li>-c: an integer representing pseudocount constant for PSI-BLAST. Default = 7</li> 376 * <li>-F: any filtering directive</li> 377 * </ul> 378 * <p> 379 * WARNING!! This method is still very much in flux and might not work as expected... 380 * </p> 381 * <p> 382 * You have to be aware that at no moment is there any error checking on the use of these parameters by this class. 383 * </p> 384 * 385 * @param advancedOptions : a String with any number of optional parameters with an associated value. 386 */ 387 public void setBlastAdvancedOptions(String advancedOptions) { 388 // Escaping white spaces with + char to comply with QBlast specifications 389 setAlignmentOption(OTHER_ADVANCED, advancedOptions.replaceAll(" ", "+")); 390 } 391 392 /** 393 * @return the String with the advanced options 394 */ 395 public String getBlastAdvancedOptions() { 396 return getAlignmentOption(OTHER_ADVANCED); 397 } 398}