PageRenderTime 48ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/primer3-2.3.4/src/thal_main.c

#
C | 339 lines | 281 code | 10 blank | 48 comment | 84 complexity | 9116ac17baa86d587064f944933e2081 MD5 | raw file
Possible License(s): GPL-2.0
  1. /*
  2. Copyright (c) 1996,1997,1998,1999,2000,2001,2004,2006,2007,2008,2009
  3. Whitehead Institute for Biomedical Research, Steve Rozen
  4. (http://purl.com/STEVEROZEN/), and Helen Skaletsky
  5. All rights reserved.
  6. This file is part of primer3 software suite.
  7. This software suite is is free software;
  8. you can redistribute it and/or modify it under the terms
  9. of the GNU General Public License as published by the Free
  10. Software Foundation; either version 2 of the License, or (at
  11. your option) any later version.
  12. This software is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. GNU General Public License for more details.
  16. You should have received a copy of the GNU General Public License
  17. along with this software (file gpl-2.0.txt in the source
  18. distribution); if not, write to the Free Software
  19. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  20. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23. A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24. OWNERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25. SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26. LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON A THEORY
  28. OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. */
  32. #include <limits.h>
  33. #include <errno.h>
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include <string.h>
  37. #include <setjmp.h>
  38. #include <ctype.h>
  39. #include <math.h>
  40. #include <unistd.h>
  41. #include <sys/types.h>
  42. #include <sys/stat.h>
  43. #include "thal.h"
  44. /* Check on which OS we compile */
  45. #if defined(_WIN32) || defined(WIN32) || defined (__WIN32__) || defined(__CYGWIN__) || defined(__MINGW32__)
  46. #define OS_WIN
  47. #endif
  48. #define DEBUG
  49. char *endptr; /* reading input */
  50. int i; /* index */
  51. const unsigned char *oligo1, *oligo2; /* inserted oligo sequences */
  52. char *path = NULL; /* path to the parameter files */
  53. /* Beginning of main */
  54. int main(int argc, char** argv)
  55. {
  56. const char* usage;
  57. int tmp_ret;
  58. thal_args a;
  59. thal_results o;
  60. set_thal_default_args(&a);
  61. a.temponly=0; /* by default print only melting temperature,
  62. do not draw structure or print any additional parameters */
  63. if(a.debug == 0) {
  64. #undef DEBUG
  65. } else {
  66. #define DEBUG
  67. }
  68. usage = "USAGE: %s OPTIONS oligo\n"
  69. "-mv monovalent_conc - concentration of monovalent cations in mM, by default 50 mM\n"
  70. "\n"
  71. "-dv divalent_conc - concentration of divalent cations in mM, by default 0 mM\n"
  72. "\n"
  73. "-n dNTP_conc - concentration of deoxynycleotide triphosphate in mM, by default 0 mM\n"
  74. "\n"
  75. "-d dna_conc - concentration of DNA strands in nM, by default 50 nM\n"
  76. "\n"
  77. "-a mode - alignment type, END1, END2, ANY and HAIRPIN, by default ANY (when duplex)\n"
  78. "\n"
  79. "-t temp - temperature at which duplex is calculated, by default 37C\n"
  80. "\n"
  81. "-r - causes the alignment NOT to be displayed on stderr, _only_ Tm is printed\n"
  82. "\n"
  83. "-maxloop size - the maximum size of secondary structures loops.\n"
  84. " Default is 30 (this is maximum allowed length, currently).\n"
  85. "\n"
  86. "-path <path> - the path to the thermodynamic parameter files\n"
  87. "\n"
  88. "-s1 DNA_oligomer\n"
  89. "\n"
  90. "-s2 DNA_oligomer\n"
  91. "\n";
  92. if(argc < 2) {
  93. #ifdef DEBUG
  94. fprintf(stderr, usage, argv[0]);
  95. #endif
  96. return -1;
  97. }
  98. /* BEGIN: READ the INPUT */
  99. for(i = 1; i < argc; ++i) {
  100. if (!strncmp("-mv", argv[i], 3)) { /* conc of monovalent cations */
  101. if(argv[i+1]==NULL) {
  102. #ifdef DEBUG
  103. fprintf(stderr, usage, argv[0]);
  104. #endif
  105. exit(-1);
  106. }
  107. a.mv = strtod(argv[i+1], &endptr);
  108. if ('\0' != *endptr || a.mv < 0.0) {
  109. #ifdef DEBUG
  110. fprintf(stderr, usage, argv[0]);
  111. #endif
  112. exit(-1);
  113. }
  114. i++;
  115. } else if (!strncmp("-dv", argv[i], 3)) { /* conc of divalent cations */
  116. if(argv[i+1]==NULL) {
  117. #ifdef DEBUG
  118. fprintf(stderr, usage, argv[0]);
  119. #endif
  120. exit(-1);
  121. }
  122. a.dv = strtod(argv[i+1], &endptr);
  123. if('\0' != *endptr || a.dv < 0.0) {
  124. #ifdef DEBUG
  125. fprintf(stderr, usage, argv[0]);
  126. #endif
  127. exit(-1);
  128. }
  129. i++;
  130. } else if (!strcmp("-path", argv[i])) {
  131. if(argv[i+1]==NULL) {
  132. #ifdef DEBUG
  133. fprintf(stderr, usage, argv[0]);
  134. #endif
  135. exit(-1);
  136. }
  137. path = (char*)argv[i+1];
  138. i++;
  139. } else if (!strncmp("-s1", argv[i], 3)) { /* first sequence in 5'->3' direction */
  140. if(argv[i+1]==NULL) {
  141. #ifdef DEBUG
  142. fprintf(stderr, usage, argv[0]);
  143. #endif
  144. exit(-1);
  145. }
  146. oligo1 = (const unsigned char*)argv[i+1];
  147. i++;
  148. } else if (!strncmp("-s2", argv[i], 3)) { /* second sequence in 5'->3' direction */
  149. if(argv[i+1]==NULL) {
  150. #ifdef DEBUG
  151. fprintf(stderr, usage, argv[0]);
  152. #endif
  153. exit(-1);
  154. }
  155. oligo2 = (const unsigned char*)argv[i+1];
  156. i++;
  157. } else if (!strncmp("-a", argv[i], 2)) { /* annealing type END1, END2, ANY, considered only when duplexis;
  158. by default ANY */
  159. if(argv[i+1]==NULL) {
  160. #ifdef DEBUG
  161. fprintf(stderr, usage, argv[0]);
  162. #endif
  163. exit(-1);
  164. }
  165. if(strcmp(argv[i+1],"END1")==0) {
  166. a.type = thal_end1;
  167. } else if(strcmp(argv[i+1],"END2")==0) {
  168. a.type = thal_end2;
  169. } else if(strcmp(argv[i+1],"HAIRPIN")==0) {
  170. a.type = thal_hairpin;
  171. a.dimer = 0;
  172. } else if (strcmp(argv[i+1], "ANY")==0) {
  173. a.type = thal_any; /* ANY */
  174. } else {
  175. #ifdef DEBUG
  176. fprintf(stderr, usage, argv[0]);
  177. #endif
  178. exit(-1);
  179. }
  180. i++;
  181. } else if (!strncmp("-d", argv[i], 2)) { /* dna conc */
  182. if(argv[i+1]==NULL) {
  183. #ifdef DEBUG
  184. fprintf(stderr, usage, argv[0]);
  185. #endif
  186. exit(-1);
  187. }
  188. a.dna_conc = strtod(argv[i+1], &endptr);
  189. if('\0' != *endptr || a.dna_conc < 0 || a.dna_conc == 0) {
  190. #ifdef DEBUG
  191. fprintf(stderr, usage, argv[0]);
  192. #endif
  193. exit(-1);
  194. }
  195. i++;
  196. } else if (!strncmp("-r", argv[i], 2)) { /* only temp is calculated */
  197. a.temponly = 1;
  198. } else if (!strncmp("-t", argv[i], 2)) { /* temperature at which sec str are calculated */
  199. if(argv[i+1]==NULL) {
  200. #ifdef DEBUG
  201. fprintf(stderr, usage, argv[0]);
  202. #endif
  203. exit(-1);
  204. }
  205. a.temp = strtod(argv[i+1], &endptr) + ABSOLUTE_ZERO;
  206. if('\0' != *endptr) {
  207. #ifdef DEBUG
  208. fprintf(stderr, usage, argv[0]);
  209. #endif
  210. exit(-1);
  211. }
  212. i++;
  213. } else if (!strncmp("-n", argv[i], 2)) { /* concentration of dNTPs */
  214. if(argv[i+1]==NULL) {
  215. #ifdef DEBUG
  216. fprintf(stderr, usage, argv[0]);
  217. #endif
  218. exit(-1);
  219. }
  220. a.dntp = strtod(argv[i+1], &endptr);
  221. if('\0' != *endptr || a.dntp < 0.0) {
  222. #ifdef DEBUG
  223. fprintf(stderr, usage, argv[0]);
  224. #endif
  225. exit(-1);
  226. }
  227. i++;
  228. } else if (!strncmp("-maxloop", argv[i], 8)) { /* maximum size of loop calculated;
  229. this value can not be larger than 30 */
  230. if(argv[i+1]==NULL) {
  231. #ifdef DEBUG
  232. fprintf(stderr, usage, argv[0]);
  233. #endif
  234. exit(-1);
  235. }
  236. a.maxLoop = (int) (strtod(argv[i+1], &endptr));
  237. if(a.maxLoop > MAX_LOOP ) {
  238. a.maxLoop = MAX_LOOP;
  239. #ifdef DEBUG
  240. fputs("Warning: the maximum size of secondary structures loop is set to default (30)\n", stderr);
  241. #endif
  242. } else if(a.maxLoop < MIN_LOOP) {
  243. a.maxLoop = MIN_LOOP;
  244. #ifdef DEBUG
  245. fputs("Warning: the maximum size of secondary structures loop was set to minimum size of allowed loop length (0)\n", stderr);
  246. #endif
  247. }
  248. if('\0' != *endptr || a.maxLoop < 0) {
  249. #ifdef DEBUG
  250. fprintf(stderr, usage, argv[0]);
  251. #endif
  252. exit(-1);
  253. }
  254. i++;
  255. } else if(!strncmp("-", argv[i], 1)) { /* Unknown option. */
  256. #ifdef DEBUG
  257. fprintf(stderr, usage, argv[0]);
  258. #endif
  259. exit(-1);
  260. } else {
  261. break;
  262. }
  263. }
  264. /* END reading INPUT */
  265. /* check the input correctness */
  266. if(a.dimer!=0 && (oligo2==NULL || oligo1==NULL)) { /* if user wants to calculate structure
  267. of dimer then two sequences must be defined*/
  268. fprintf(stderr, usage, argv[0]);
  269. exit(-1);
  270. }
  271. if(a.dimer==0 && (oligo2==NULL && oligo1==NULL)) { /* if user wants to calculate structure
  272. of monomer then only one sequence must be defined */
  273. fprintf(stderr, usage, argv[0]);
  274. exit(-1);
  275. }
  276. /* read thermodynamic parameters */
  277. if (path == NULL) {
  278. /* check for the default paths */
  279. struct stat st;
  280. #ifdef OS_WIN
  281. if ((stat(".\\primer3_config", &st) == 0) && S_ISDIR(st.st_mode)) {
  282. tmp_ret = get_thermodynamic_values(".\\primer3_config\\", &o);
  283. } else {
  284. /* no default directory found, error */
  285. fprintf(stderr, "Error: thermodynamic approach chosen, but path to thermodynamic parameters not specified\n");
  286. exit(-1);
  287. }
  288. #else
  289. if ((stat("./primer3_config", &st) == 0) && S_ISDIR(st.st_mode)) {
  290. tmp_ret = get_thermodynamic_values("./primer3_config/", &o);
  291. } else if ((stat("/etc/primer3_config", &st) == 0) && S_ISDIR(st.st_mode)) {
  292. tmp_ret = get_thermodynamic_values("/etc/primer3_config/", &o);
  293. } else {
  294. /* no default directory found, error */
  295. fprintf(stderr, "Error: thermodynamic approach chosen, but path to thermodynamic parameters not specified\n");
  296. exit(-1);
  297. }
  298. #endif
  299. } else tmp_ret = get_thermodynamic_values(path, &o);
  300. if (tmp_ret) {
  301. fprintf(stderr, "%s\n", o.msg);
  302. exit(-1);
  303. }
  304. /* execute thermodynamical alignemnt */
  305. if(a.dimer==0 && oligo1!=NULL){
  306. thal(oligo1,oligo1,&a,&o);
  307. } else if(a.dimer==0 && oligo1==NULL && oligo2!=NULL) {
  308. thal(oligo2,oligo2,&a,&o);
  309. } else {
  310. thal(oligo1,oligo2,&a,&o);
  311. }
  312. /* encountered error during thermodynamical calc */
  313. if (o.temp == THAL_ERROR_SCORE) {
  314. tmp_ret = fprintf(stderr, "Error: %s\n", o.msg);
  315. exit(-1);
  316. }
  317. if(a.temponly==1)
  318. printf("%f\n",o.temp);
  319. /* cleanup */
  320. destroy_thal_structures();
  321. return EXIT_SUCCESS;
  322. }