PageRenderTime 49ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/scaffoldOptimizer/Configuration.cpp

http://tud-scaffolding.googlecode.com/
C++ | 640 lines | 605 code | 6 blank | 29 comment | 148 complexity | 057df0a2fd9acdbe6912381c270bf9c4 MD5 | raw file
Possible License(s): GPL-3.0
  1. /*
  2. * scaffoldOptimizer : solves the MIQP optimization and produces linear scaffold
  3. * sequences.
  4. * Copyright (C) 2011 Alexey Gritsenko
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see http://www.gnu.org/licenses/.
  18. *
  19. *
  20. *
  21. * Email: a.gritsenko@tudelft.nl
  22. * Mail: Delft University of Technology
  23. * Faculty of Electrical Engineering, Mathematics, and Computer Science
  24. * Department of Mediamatics
  25. * P.O. Box 5031
  26. * 2600 GA, Delft, The Netherlands
  27. */
  28. #include "Configuration.h"
  29. #include "Defines.h"
  30. #include "Helpers.h"
  31. #include <iostream>
  32. #include <cstring>
  33. #include <cstdlib>
  34. #include <sstream>
  35. using namespace std;
  36. // Construtor with default configuration parameter settings.
  37. Configuration::Configuration()
  38. {
  39. Success = false;
  40. RemoveAmbiguous = true;
  41. Sort = true;
  42. Bundle = true;
  43. BundlePerGroup = false;
  44. BundleAmbiguous = true;
  45. PrintMatrix = false;
  46. BundleDistance = 3.0;
  47. Erosion = 5.0;
  48. ExpectedCoverage = 0.0;
  49. UniquenessFCutoff = 5.0;
  50. InputFileName = "";
  51. ReadCoverageFileName = "";
  52. OutputFileName = "scaffold.fasta";
  53. SolutionOutputFileName = "";
  54. }
  55. // Parses command line arguments. Returns true if successful.
  56. bool Configuration::ProcessCommandLine(int argc, char *argv[])
  57. {
  58. this->Success = true;
  59. stringstream serr;
  60. if (argc == 1)
  61. {
  62. serr << "[-] Not enough arguments. Consult -help." << endl;
  63. this->Success = false;
  64. }
  65. else
  66. {
  67. int i = 1;
  68. while (i < argc)
  69. {
  70. if (!strcmp("-help", argv[i]) || !strcmp("-h", argv[i]))
  71. {
  72. printHelpMessage(serr);
  73. this->Success = false;
  74. break;
  75. }
  76. else if (!strcmp("-ambiguous", argv[i]))
  77. {
  78. if (argc - i - 1 < 1)
  79. {
  80. cerr << "[-] Parsing error in -ambiguous: must have an argument." << endl;
  81. this->Success = false;
  82. break;
  83. }
  84. i++;
  85. bool sw = false;
  86. if (!strcasecmp(argv[i], "yes"))
  87. sw = true;
  88. else if (!strcasecmp(argv[i], "no"))
  89. sw = false;
  90. else
  91. {
  92. cerr << "[-] Parsing error in -ambiguous: argument must be yes/no." << endl;
  93. this->Success = false;
  94. break;
  95. }
  96. RemoveAmbiguous = !sw;
  97. }
  98. else if (!strcmp("-sort", argv[i]))
  99. {
  100. if (argc - i - 1 < 1)
  101. {
  102. cerr << "[-] Parsing error in -sort: must have an argument." << endl;
  103. this->Success = false;
  104. break;
  105. }
  106. i++;
  107. bool sw = false;
  108. if (!strcasecmp(argv[i], "yes"))
  109. sw = true;
  110. else if (!strcasecmp(argv[i], "no"))
  111. sw = false;
  112. else
  113. {
  114. cerr << "[-] Parsing error in -sort: argument must be yes/no." << endl;
  115. this->Success = false;
  116. break;
  117. }
  118. Sort = sw;
  119. }
  120. else if (!strcmp("-bundle", argv[i]))
  121. {
  122. if (argc - i - 1 < 1)
  123. {
  124. cerr << "[-] Parsing error in -bundle: must have an argument." << endl;
  125. this->Success = false;
  126. break;
  127. }
  128. i++;
  129. bool sw = false;
  130. if (!strcasecmp(argv[i], "yes"))
  131. sw = true;
  132. else if (!strcasecmp(argv[i], "no"))
  133. sw = false;
  134. else
  135. {
  136. cerr << "[-] Parsing error in -bundle: argument must be yes/no." << endl;
  137. this->Success = false;
  138. break;
  139. }
  140. Bundle = sw;
  141. }
  142. else if (!strcmp("-bundle-groups", argv[i]))
  143. {
  144. if (argc - i - 1 < 1)
  145. {
  146. cerr << "[-] Parsing error in -bundle-groups: must have an argument." << endl;
  147. this->Success = false;
  148. break;
  149. }
  150. i++;
  151. bool sw = false;
  152. if (!strcasecmp(argv[i], "yes"))
  153. sw = true;
  154. else if (!strcasecmp(argv[i], "no"))
  155. sw = false;
  156. else
  157. {
  158. cerr << "[-] Parsing error in -bundle-groups: argument must be yes/no." << endl;
  159. this->Success = false;
  160. break;
  161. }
  162. BundlePerGroup = !sw;
  163. }
  164. else if (!strcmp("-bundle-ambiguous", argv[i]))
  165. {
  166. if (argc - i - 1 < 1)
  167. {
  168. cerr << "[-] Parsing error in -bundle-ambiguous: must have an argument." << endl;
  169. this->Success = false;
  170. break;
  171. }
  172. i++;
  173. bool sw = false;
  174. if (!strcasecmp(argv[i], "yes"))
  175. sw = true;
  176. else if (!strcasecmp(argv[i], "no"))
  177. sw = false;
  178. else
  179. {
  180. cerr << "[-] Parsing error in -bundle-ambiguous: argument must be yes/no." << endl;
  181. this->Success = false;
  182. break;
  183. }
  184. BundleAmbiguous = sw;
  185. }
  186. else if (!strcmp("-bundle-distance", argv[i]))
  187. {
  188. if (argc - i - 1 < 1)
  189. {
  190. cerr << "[-] Parsing error in -bundle-distance: must have an argument." << endl;
  191. this->Success = false;
  192. break;
  193. }
  194. i++;
  195. bool distanceSuccess;
  196. int distance = Helpers::ParseInt(argv[i], distanceSuccess);
  197. if (!distanceSuccess || distance <= 0)
  198. {
  199. cerr << "[-] Parsing error in -bundle-distance: distance must be a positive number." << endl;
  200. this->Success = false;
  201. break;
  202. }
  203. BundleDistance = distance;
  204. }
  205. else if (!strcmp("-repeat-coverage", argv[i]))
  206. {
  207. if (argc - i - 1 < 2)
  208. {
  209. cerr << "[-] Parsing error in -repeat-coverage: must have at least two arguments argument." << endl;
  210. this->Success = false;
  211. break;
  212. }
  213. i++;
  214. bool expectedCoverageSuccess;
  215. int expectedCoverage = Helpers::ParseInt(argv[i], expectedCoverageSuccess);
  216. if (!expectedCoverageSuccess || expectedCoverage <= 0)
  217. {
  218. cerr << "[-] Parsing error in -repeat-coverage: expected coverage must be a positive number." << endl;
  219. this->Success = false;
  220. break;
  221. }
  222. ExpectedCoverage = expectedCoverage;
  223. i++;
  224. ReadCoverageFileName = argv[i];
  225. if (argc - i - 1 >= 1 && Helpers::IsNumber(argv[i + 1]))
  226. {
  227. i++;
  228. bool uniquenessFCutoffSuccess;
  229. int uniquenessFCutoff = Helpers::ParseInt(argv[i], uniquenessFCutoffSuccess);
  230. if (!uniquenessFCutoffSuccess || uniquenessFCutoff <= 0)
  231. {
  232. cerr << "[i] Parsing error in -repeat-coverage: uniqueness F cutoff must be a position number." << endl;
  233. this->Success = false;
  234. break;
  235. }
  236. UniquenessFCutoff = uniquenessFCutoff;
  237. }
  238. }
  239. else if (!strcmp("-erosion", argv[i]))
  240. {
  241. if (argc - i - 1 < 1)
  242. {
  243. cerr << "[-] Parsing error in -erosion: must have an argument." << endl;
  244. this->Success = false;
  245. break;
  246. }
  247. i++;
  248. bool erosionSuccess;
  249. int erosion = Helpers::ParseInt(argv[i], erosionSuccess);
  250. if (!erosionSuccess || erosion < 0)
  251. {
  252. cerr << "[-] Parsing error in -erosion: distance must be a non-negative number." << endl;
  253. this->Success = false;
  254. break;
  255. }
  256. Erosion = erosion;
  257. }
  258. else if (!strcmp("-overlap-deviation", argv[i]))
  259. {
  260. if (argc - i - 1 < 1)
  261. {
  262. cerr << "[-] Parsing error in -overlap-deviation: must have an argument." << endl;
  263. this->Success = false;
  264. break;
  265. }
  266. i++;
  267. bool deviationSuccess;
  268. int deviation = Helpers::ParseInt(argv[i], deviationSuccess);
  269. if (!deviationSuccess || deviation < 0)
  270. {
  271. cerr << "[-] Parsing error in -overlap-deviation: length must be a non-negative number." << endl;
  272. this->Success = false;
  273. break;
  274. }
  275. OverlapperOptions.InitialOverlapDeviation = deviation;
  276. }
  277. else if (!strcmp("-max-alignment", argv[i]))
  278. {
  279. if (argc - i - 1 < 1)
  280. {
  281. cerr << "[-] Parsing error in -max-alignment: must have an argument." << endl;
  282. this->Success = false;
  283. break;
  284. }
  285. i++;
  286. bool maxAlignemntSuccess;
  287. int maxAlignemnt = Helpers::ParseInt(argv[i], maxAlignemntSuccess);
  288. if (!maxAlignemntSuccess || maxAlignemnt < 0)
  289. {
  290. cerr << "[-] Parsing error in -max-alignment: length must be a non-negative number." << endl;
  291. this->Success = false;
  292. break;
  293. }
  294. OverlapperOptions.MaximumAlignmentLength = maxAlignemnt;
  295. }
  296. else if (!strcmp("-no-split", argv[i]))
  297. {
  298. if (argc - i - 1 < 1)
  299. {
  300. cerr << "[-] Parsing error in -no-split: must have an argument." << endl;
  301. this->Success = false;
  302. break;
  303. }
  304. i++;
  305. bool noSplitSuccess;
  306. int noSplit = Helpers::ParseInt(argv[i], noSplitSuccess);
  307. if (!noSplitSuccess || noSplit < 0)
  308. {
  309. cerr << "[-] Parsing error in -no-split: length must be a non-negative number." << endl;
  310. this->Success = false;
  311. break;
  312. }
  313. OverlapperOptions.NoSplitOverlapLength = noSplit;
  314. }
  315. else if (!strcmp("-output", argv[i]))
  316. {
  317. if (argc - i - 1 < 1)
  318. {
  319. serr << "[-] Parsing error in -output: must have an argument." << endl;
  320. this->Success = false;
  321. break;
  322. }
  323. i++;
  324. OutputFileName = argv[i];
  325. }
  326. else if (!strcmp("-solution-output", argv[i]))
  327. {
  328. if (argc - i - 1 < 1)
  329. {
  330. serr << "[-] Parsing error in -solution-output: must have an argument." << endl;
  331. this->Success = false;
  332. break;
  333. }
  334. i++;
  335. SolutionOutputFileName = argv[i];
  336. }
  337. else if (!strcmp("-print-matrix", argv[i]))
  338. {
  339. if (argc - i - 1 < 1)
  340. {
  341. cerr << "[-] Parsing error in -print-matrix: must have an argument." << endl;
  342. this->Success = false;
  343. break;
  344. }
  345. i++;
  346. bool sw = false;
  347. if (!strcasecmp(argv[i], "yes"))
  348. sw = true;
  349. else if (!strcasecmp(argv[i], "no"))
  350. sw = false;
  351. else
  352. {
  353. cerr << "[-] Parsing error in -print-matrix: argument must be yes/no." << endl;
  354. this->Success = false;
  355. break;
  356. }
  357. PrintMatrix = sw;
  358. }
  359. else if (!strcmp("-time-limit", argv[i]))
  360. {
  361. if (argc - i - 1 < 1)
  362. {
  363. cerr << "[-] Parsing error in -time-limit: must have an argument." << endl;
  364. this->Success = false;
  365. break;
  366. }
  367. i++;
  368. bool timeLimitSuccess;
  369. int timeLimit = Helpers::ParseInt(argv[i], timeLimitSuccess);
  370. if (!timeLimitSuccess || timeLimit < 0)
  371. {
  372. cerr << "[-] Parsing error in -time-limit: time must be a positive number." << endl;
  373. this->Success = false;
  374. break;
  375. }
  376. Options.TimeLimit = timeLimit;
  377. }
  378. else if (!strcmp("-threads", argv[i]))
  379. {
  380. if (argc - i - 1 < 1)
  381. {
  382. cerr << "[-] Parsing error in -threads: must have an argument." << endl;
  383. this->Success = false;
  384. break;
  385. }
  386. i++;
  387. bool threadsSuccess;
  388. int threads = Helpers::ParseInt(argv[i], threadsSuccess);
  389. if (!threadsSuccess || threads < 0)
  390. {
  391. cerr << "[-] Parsing error in -threads: number of threads must be a non-negative number." << endl;
  392. this->Success = false;
  393. break;
  394. }
  395. Options.Threads = threads;
  396. }
  397. else if (!strcmp("-cplex-opportunistic", argv[i]))
  398. {
  399. if (argc - i - 1 < 1)
  400. {
  401. cerr << "[-] Parsing error in -cplex-opportunistic: must have an argument." << endl;
  402. this->Success = false;
  403. break;
  404. }
  405. i++;
  406. bool sw = false;
  407. if (!strcasecmp(argv[i], "yes"))
  408. sw = true;
  409. else if (!strcasecmp(argv[i], "no"))
  410. sw = false;
  411. else
  412. {
  413. cerr << "[-] Parsing error in -cplex-opportunistic: argument must be yes/no." << endl;
  414. this->Success = false;
  415. break;
  416. }
  417. Options.UseOpportunisticSearch = sw;
  418. }
  419. else if (!strcmp("-cplex-heuristic", argv[i]))
  420. {
  421. if (argc - i - 1 < 1)
  422. {
  423. cerr << "[-] Parsing error in -cplex-heuristic: must have an argument." << endl;
  424. this->Success = false;
  425. break;
  426. }
  427. i++;
  428. bool sw = false;
  429. if (!strcasecmp(argv[i], "yes"))
  430. sw = true;
  431. else if (!strcasecmp(argv[i], "no"))
  432. sw = false;
  433. else
  434. {
  435. cerr << "[-] Parsing error in -cplex-heuristic: argument must be yes/no." << endl;
  436. this->Success = false;
  437. break;
  438. }
  439. Options.UseObjectiveHeuristic = sw;
  440. }
  441. else if (!strcmp("-cplex-suppress", argv[i]))
  442. {
  443. if (argc - i - 1 < 1)
  444. {
  445. cerr << "[-] Parsing error in -cplex-suppress: must have an argument." << endl;
  446. this->Success = false;
  447. break;
  448. }
  449. i++;
  450. bool sw = false;
  451. if (!strcasecmp(argv[i], "yes"))
  452. sw = true;
  453. else if (!strcasecmp(argv[i], "no"))
  454. sw = false;
  455. else
  456. {
  457. cerr << "[-] Parsing error in -cplex-suppress: argument must be yes/no." << endl;
  458. this->Success = false;
  459. break;
  460. }
  461. Options.SuppressOutput = sw;
  462. }
  463. else if (!strcmp("-lp-limit", argv[i]))
  464. {
  465. if (argc - i - 1 < 1)
  466. {
  467. cerr << "[-] Parsing error in -lp-limit: must have an argument." << endl;
  468. this->Success = false;
  469. break;
  470. }
  471. i++;
  472. bool timeLimitSuccess;
  473. int timeLimit = Helpers::ParseInt(argv[i], timeLimitSuccess);
  474. if (!timeLimitSuccess || timeLimit < 0)
  475. {
  476. cerr << "[-] Parsing error in -lp-limit: time must be a positive number." << endl;
  477. this->Success = false;
  478. break;
  479. }
  480. Options.LPTimeLimit = timeLimit;
  481. }
  482. else if (!strcmp("-lp-threads", argv[i]))
  483. {
  484. if (argc - i - 1 < 1)
  485. {
  486. cerr << "[-] Parsing error in -lp-threads: must have an argument." << endl;
  487. this->Success = false;
  488. break;
  489. }
  490. i++;
  491. bool threadsSuccess;
  492. int threads = Helpers::ParseInt(argv[i], threadsSuccess);
  493. if (!threadsSuccess || threads < 0)
  494. {
  495. cerr << "[-] Parsing error in -lp-threads: number of threads must be a non-negative number." << endl;
  496. this->Success = false;
  497. break;
  498. }
  499. Options.LPThreads = threads;
  500. }
  501. else if (!strcmp("-lp-attempts", argv[i]))
  502. {
  503. if (argc - i - 1 < 1)
  504. {
  505. cerr << "[-] Parsing error in -lp-attempts: must have an argument." << endl;
  506. this->Success = false;
  507. break;
  508. }
  509. i++;
  510. bool attemptsSuccess;
  511. int attempts = Helpers::ParseInt(argv[i], attemptsSuccess);
  512. if (!attemptsSuccess || attempts < 0)
  513. {
  514. cerr << "[-] Parsing error in -lp-attempts: number of attempts must be a non-negative number." << endl;
  515. this->Success = false;
  516. break;
  517. }
  518. Options.LPAttempts = attempts;
  519. }
  520. else if (!strcmp("-ga-limit", argv[i]))
  521. {
  522. if (argc - i - 1 < 1)
  523. {
  524. cerr << "[-] Parsing error in -ga-limit: must have an argument." << endl;
  525. this->Success = false;
  526. break;
  527. }
  528. i++;
  529. bool timeLimitSuccess;
  530. int timeLimit = Helpers::ParseInt(argv[i], timeLimitSuccess);
  531. if (!timeLimitSuccess || timeLimit < 0)
  532. {
  533. cerr << "[-] Parsing error in -ga-limit: time must be a positive number." << endl;
  534. this->Success = false;
  535. break;
  536. }
  537. Options.GATimeLimit = timeLimit;
  538. }
  539. else if (!strcmp("-ga-restarts", argv[i]))
  540. {
  541. if (argc - i - 1 < 1)
  542. {
  543. cerr << "[-] Parsing error in -ga-restarts: must have an argument." << endl;
  544. this->Success = false;
  545. break;
  546. }
  547. i++;
  548. bool restartsSuccess;
  549. int restarts = Helpers::ParseInt(argv[i], restartsSuccess);
  550. if (!restartsSuccess || restarts < 0)
  551. {
  552. cerr << "[-] Parsing error in -ga-restarts: number of attempts must be a non-negative number." << endl;
  553. this->Success = false;
  554. break;
  555. }
  556. Options.GARestarts = restarts;
  557. }
  558. else if (!strcmp("-verbose", argv[i]))
  559. {
  560. if (argc - i - 1 < 1)
  561. {
  562. cerr << "[-] Parsing error in -verbose: must have an argument." << endl;
  563. this->Success = false;
  564. break;
  565. }
  566. i++;
  567. int sw = 0;
  568. if (!strcasecmp(argv[i], "yes"))
  569. sw = 1;
  570. else if (!strcasecmp(argv[i], "no"))
  571. sw = 0;
  572. else if (!strcasecmp(argv[i], "more"))
  573. sw = 2;
  574. else
  575. {
  576. cerr << "[-] Parsing error in -verbose: argument must be yes/no/more." << endl;
  577. this->Success = false;
  578. break;
  579. }
  580. Options.VerboseOutput = sw;
  581. }
  582. else if (i == argc - 1)
  583. this->InputFileName = argv[argc - 1];
  584. else
  585. {
  586. serr << "[-] Unknown argument: " << argv[i] << endl;
  587. this->Success = false;
  588. break;
  589. }
  590. i++;
  591. }
  592. if (this->InputFileName == "")
  593. {
  594. serr << "[-] No input file specified." << endl;
  595. this->Success = false;
  596. }
  597. }
  598. if (!this->Success)
  599. LastError = serr.str();
  600. return this->Success;
  601. }
  602. void Configuration::printHelpMessage(stringstream &serr)
  603. {
  604. serr << "[i] Scaffold optimizer version " << VERSION << " (" << DATE << ")" << endl;
  605. serr << "[i] By " << AUTHOR << endl;
  606. serr << "[i] Usage: scaffoldOptimizer [arguments] <scaffold.opt>" << endl;
  607. serr << "[i] -help Print this message and exit." << endl;
  608. serr << "[i] -ambiguous <yes/no> Use ambiguous contig links in optimization formulation. [no]" << endl;
  609. serr << "[i] -sort <yes/no> Sort contig links in order to reduce non-zero elements in the optimization matrix. [yes]" << endl;
  610. serr << "[i] -bundle <yes/no> Bundle contig links together? [yes]" << endl;
  611. serr << "[i] -bundle-groups <yes/no> Bundle contig links from different link groups? [yes]" << endl;
  612. serr << "[i] -bundle-ambiguous <yes/no> Bundle ambiguous and non-ambiguous contig links together? [yes]" << endl;
  613. serr << "[i] -bundle-distance <distance> Bundle contig links withing <distance> standard deviation from the median. [3]" << endl;
  614. serr << "[i] -repeat-coverage <exp. cov.> <cov. filename> [F] Detect repeats using expected coverage and read coverage provided in a file. [5]" << endl;
  615. serr << "[i] -erosion <weight> Remove contig links with weight smaller than <weigth> (should be used only with link bundling). [5]" << endl;
  616. serr << endl;
  617. serr << "[i] -overlap-deviation <length> Length by which contig distance is reduced to find better overlaps. [100]" << endl;
  618. serr << "[i] -max-alignment <length> Maximum contig overlap to perform global alignment on. Overlap deviation is not taken into account. [1500]" << endl;
  619. serr << "[i] -no-split <length> Maximum predicted overlap length that is not confirmed by alignment, which does not cause scaffold splitting. [50]" << endl;
  620. serr << endl;
  621. serr << "[i] -time-limit <seconds> Time limit for a single run of CPLEX or GA in seconds. [infinite]" << endl;
  622. serr << "[i] -threads <n> Number of threads a solver can use. [automatic]" << endl;
  623. serr << "[i] -cplex-opportunistic <yes/no> Use CPLEX opportunistic optimization mode. [yes]" << endl;
  624. serr << "[i] -cplex-heuristic <yes/no> Use CPLEX objective function heuristic. [yes]" << endl;
  625. serr << "[i] -cplex-suppress <yes/no> Suppress CPLEX output. [yes]" << endl;
  626. serr << "[i] -lp-limit <seconds> Time in secconds for solving a single fixed optimization problem. [30]" << endl;
  627. serr << "[i] -lp-threads <seconds> Number of threads used for solving a single fixed optimization problem. [automatic]" << endl;
  628. serr << "[i] -lp-attempts <number> Number of attempts to solve a single fixed optimization problem. [3]" << endl;
  629. serr << "[i] -ga-limit <seconds> Time in seconds for solving a single GA optimization problem. [unlimited]" << endl;
  630. serr << "[i] -ga-restarts <number> Number of restarts before exiting GA optimization. [unlimited]" << endl;
  631. serr << "[i] -verbose <yes/no/more> Verbose output of solvers? [no]" << endl;
  632. serr << "[i] -output <output filename> Output filename for final scaffolds. [scaffold.fasta]" << endl;
  633. serr << "[i] -solution-output <output filename> Output filename for optimzation solution. [not output]" << endl;
  634. }