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<>(); 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<>(); 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 && "on".equals(getAlignmentOption(MEGABLAST)); 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 * Blastall equivalent: -d 141 * 142 * @param database a valid name to a NCBI blastable database 143 */ 144 public void setBlastDatabase(String database) { 145 setAlignmentOption(DATABASE, database); 146 } 147 148 /** 149 * @return double value of EXPECT parameter used for blast run 150 */ 151 public double getBlastExpect() { 152 if (param.containsKey(EXPECT)) { 153 return Double.parseDouble(getAlignmentOption(EXPECT)); 154 } 155 return 10; 156 } 157 158 /** 159 * Sets the EXPECT parameter to be use with blastall 160 * <p> 161 * Example: if you want a EXPECT of 1e-10, pass {@code Double.parseDouble("1e-10")} as a parameter 162 * <p> 163 * Blastall equivalent: -e 164 * 165 * @param expect: a double value of EXPECT parameter 166 */ 167 public void setBlastExpect(double expect) { 168 setAlignmentOption(EXPECT, Double.toString(expect)); 169 } 170 171 /** 172 * Returns the value of the WORD_SIZE parameter used for this blast run 173 * 174 * @return int value of WORD_SIZE used by this search 175 * @throws IllegalArgumentException when program type is not set and program type is not supported 176 */ 177 public int getBlastWordSize() { 178 if (param.containsKey(WORD_SIZE)) { 179 return Integer.parseInt(getAlignmentOption(WORD_SIZE)); 180 } 181 182 // return default word size value 183 try { 184 BlastProgramEnum programType = getBlastProgram(); 185 switch (programType) { 186 case blastn: 187 return 11; 188 case megablast: 189 return 28; 190 case blastp: 191 case blastx: 192 case tblastn: 193 case tblastx: 194 return 3; 195 default: 196 throw new UnsupportedOperationException("Blast program " + programType.name() + " is not supported."); 197 } 198 } catch (IllegalArgumentException e) { 199 throw new IllegalArgumentException("Blast program " + getBlastProgram() + " is not supported.", e); 200 } 201 } 202 203 /** 204 * Sets the WORD_SIZE parameter to be use with blastall 205 * <p> 206 * <b>WARNING!!</b> At this point, the method does not verify the validity of your choice; for example, word size of 207 * greater than 5 with blastp returns error messages from QBlast. Word size range depends on the algorithm chosen. 208 * <p> 209 * More at https://www.ncbi.nlm.nih.gov/staff/tao/URLAPI/new/node74.html 210 * <p> 211 * Blastall equivalent: -W 212 * 213 * @param word: an int used to set WORD_SIZE 214 */ 215 public void setBlastWordSize(int word) { 216 setAlignmentOption(WORD_SIZE, Integer.toString(word)); 217 } 218 219 /** 220 * Returns the value for the GAP_CREATION parameter (first half of GAPCOSTS parameter) 221 * 222 * @return an integer value for gap creation used by this search, -1 if not set or not a number 223 */ 224 public int getBlastGapCreation() { 225 String gapCosts = getAlignmentOption(GAPCOSTS); 226 try { 227 String gapCreation = gapCosts.split("\\+")[0]; 228 return Integer.parseInt(gapCreation); 229 } catch (Exception e) { 230 return -1; 231 } 232 } 233 234 /** 235 * Returns the value for the gap extension parameter (second half of GAPCOSTS parameter) 236 * 237 * @return an integer for the value for gap extension used by this search, -1 if not set or not a number 238 */ 239 public int getBlastGapExtension() { 240 String gapCosts = getAlignmentOption(GAPCOSTS); 241 try { 242 String gapExtension = gapCosts.split("\\+")[1]; 243 return Integer.parseInt(gapExtension); 244 } catch (Exception e) { 245 return -1; 246 } 247 } 248 249 /** 250 * Returns the actual string for the GAPCOSTS parameter which is used to build the URL 251 * 252 * @return the string representation of the GAPCOSTS parameter formatted for the URL 253 */ 254 public String getBlastGapCosts() { 255 return getAlignmentOption(GAPCOSTS); 256 } 257 258 /** 259 * Sets the GAPCOSTS parameter 260 * 261 * @param gapCreation integer to use as gap creation value 262 * @param gapExtension integer to use as gap extension value 263 */ 264 public void setBlastGapCosts(int gapCreation, int gapExtension) { 265 String gc = Integer.toString(gapCreation); 266 String ge = Integer.toString(gapExtension); 267 setAlignmentOption(GAPCOSTS, gc + "+" + ge); 268 } 269 270 /** 271 * Returns the value of the specified substitution matrix 272 * 273 * @return matrix: the name of the specified substitution matrix 274 */ 275 public String getBlastMatrix() { 276 return getAlignmentOption(MATRIX_NAME); 277 } 278 279 /** 280 * Sets the value for the MATRIX parameter to use for blastall 281 * <p> 282 * Blastall equivalent: -M 283 * 284 * @param matrix : a String to use as gap creation value 285 * @see BlastMatrixEnum 286 */ 287 public void setBlastMatrix(BlastMatrixEnum matrix) { 288 setAlignmentOption(MATRIX_NAME, matrix.name()); 289 290 boolean gapCostsSet = getBlastGapCreation() != -1 || getBlastGapExtension() != -1; 291 292 if (!gapCostsSet) { 293 /* 294 * Setting default values for -G/-E if no other values have been set is necessary because, since BLOSUM62 is 295 * default, the expected values are -G 11 -E 1. If your matrix choice is different, the request will fail, 296 * implicitly expecting GAPCOSTS=11+1 297 */ 298 switch (matrix) { 299 case PAM30: 300 setBlastGapCosts(9, 1); 301 break; 302 case PAM70: 303 setBlastGapCosts(10, 1); 304 break; 305 case PAM250: 306 setBlastGapCosts(14, 2); 307 break; 308 case BLOSUM45: 309 setBlastGapCosts(15, 2); 310 break; 311 case BLOSUM50: 312 setBlastGapCosts(13, 2); 313 break; 314 case BLOSUM80: 315 case BLOSUM90: 316 setBlastGapCosts(10, 1); 317 break; 318 case BLOSUM62: 319 break; 320 default: 321 break; 322 } 323 } 324 } 325 326 /** 327 * 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/> 328 * Blastall equivalent: -L 329 * 330 * @param start QUERY_FROM parameter 331 * @param end QUERY_TO parameter 332 */ 333 public void setBlastFromToPosition(int start, int end) { 334 if (start >= end) { 335 throw new IllegalArgumentException("Start index must be less than end index"); 336 } 337 setAlignmentOption(QUERY_FROM, String.valueOf(start)); 338 setAlignmentOption(QUERY_TO, String.valueOf(end)); 339 } 340 341 /** 342 * @return an integer value for the QUERY_FROM parameter 343 * @see #setBlastFromToPosition(int, int) 344 */ 345 public int getBlastFromPosition() { 346 return Integer.parseInt(getAlignmentOption(QUERY_FROM)); 347 } 348 349 /** 350 * @return QUERY_TO parameter 351 * @see #setBlastFromToPosition(int, int) 352 */ 353 public int getBlastToPosition() { 354 return Integer.parseInt(getAlignmentOption(QUERY_TO)); 355 } 356 357 /** 358 * This method is to be used if a request is to use non-default values at submission. Useful for the following 359 * blastall parameters: 360 * <ul> 361 * <li>-r: integer to reward for match. Default = 1</li> 362 * <li>-q: negative integer for penalty to allow mismatch. Default = -3</li> 363 * <li>-y: dropoff for blast extensions in bits, using default if not specified. Default = 20 for blastn, 7 for all 364 * others (except megablast for which it is not applicable).</li> 365 * <li>-X: X dropoff value for gapped alignment, in bits. Default = 30 for blastn/megablast, 15 for all others.</li> 366 * <li>-Z: final X dropoff value for gapped alignement, in bits. Default = 50 for blastn, 25 for all others (except 367 * megablast for which it is not applicable)</li> 368 * <li>-P: equals 0 for multiple hits 1-pass, 1 for single hit 1-pass. Does not apply to blastn ou megablast.</li> 369 * <li>-A: multiple hits window size. Default = 0 (for single hit algorithm)</li> 370 * <li>-I: number of database sequences to save hits for. Default = 500</li> 371 * <li>-Y: effective length of the search space. Default = 0 (0 represents using the whole space)</li> 372 * <li>-z: a real specifying the effective length of the database to use. Default = 0 (0 represents the real size)</li> 373 * <li>-c: an integer representing pseudocount constant for PSI-BLAST. Default = 7</li> 374 * <li>-F: any filtering directive</li> 375 * </ul> 376 * <p> 377 * WARNING!! This method is still very much in flux and might not work as expected... 378 * </p> 379 * <p> 380 * You have to be aware that at no moment is there any error checking on the use of these parameters by this class. 381 * </p> 382 * 383 * @param advancedOptions : a String with any number of optional parameters with an associated value. 384 */ 385 public void setBlastAdvancedOptions(String advancedOptions) { 386 // Escaping white spaces with + char to comply with QBlast specifications 387 setAlignmentOption(OTHER_ADVANCED, advancedOptions.replaceAll(" ", "+")); 388 } 389 390 /** 391 * @return the String with the advanced options 392 */ 393 public String getBlastAdvancedOptions() { 394 return getAlignmentOption(OTHER_ADVANCED); 395 } 396}