blast_report.tpl.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. <script type="text/javascript">
  2. window.onload = function() {
  3. if (!window.location.hash) {
  4. window.location = window.location + '#loaded';
  5. window.location.reload();
  6. }
  7. }
  8. </script>
  9. <?php
  10. /**
  11. * Display the results of a BLAST job execution
  12. *
  13. * Variables Available in this template:
  14. * $xml_filename: The full path & filename of XML file containing the BLAST results
  15. * @deepaksomanadh: $job_data = meta data related to the current job
  16. */
  17. // Set ourselves up to do link-out if our blast database is configured to do so.
  18. $linkout = FALSE;
  19. if ($blastdb->linkout->none === FALSE) {
  20. $linkout = TRUE;
  21. $linkout_regex = $blastdb->linkout->regex;
  22. //eksc- linkout vs gbrowse
  23. if (isset($blastdb->linkout->db_id->urlprefix) AND !empty($blastdb->linkout->db_id->urlprefix)) {
  24. $linkout_urlprefix = $blastdb->linkout->db_id->urlprefix;
  25. // Furthermore, check that we can determine the URL.
  26. // (ie: that the function specified to do so, exists).
  27. if (function_exists($blastdb->linkout->url_function)) {
  28. $url_function = $blastdb->linkout->url_function;
  29. }
  30. else {
  31. $linkout = FALSE;
  32. }
  33. }
  34. else {
  35. $linkout = FALSE;
  36. }
  37. }
  38. // Handle no hits. This following array will hold the names of all query
  39. // sequences which didn't have any hits.
  40. $query_with_no_hits = array();
  41. // Furthermore, if no query sequences have hits we don't want to bother listing
  42. // them all but just want to give a single, all-include "No Results" message.
  43. $no_hits = TRUE;
  44. ?>
  45. <!-- JQuery controlling display of the alignment information (hidden by default) -->
  46. <script type="text/javascript">
  47. $(document).ready(function(){
  48. // Hide the alignment rows in the table
  49. // (ie: all rows not labelled with the class "result-summary" which contains the tabular
  50. // summary of the hit)
  51. $("#blast_report tr:not(.result-summary)").hide();
  52. $("#blast_report tr:first-child").show();
  53. // When a results summary row is clicked then show the next row in the table
  54. // which should be corresponding the alignment information
  55. $("#blast_report tr.result-summary").click(function(){
  56. $(this).next("tr").toggle();
  57. $(this).find(".arrow").toggleClass("up");
  58. });
  59. });
  60. </script>
  61. <style>
  62. .no-hits-message {
  63. color: red;
  64. font-style: italic;
  65. }
  66. </style>
  67. <p><strong>Download</strong>:
  68. <a href="<?php print '../../' . $html_filename; ?>">Alignment</a>,
  69. <a href="<?php print '../../' . $tsv_filename; ?>">Tab-Delimited</a>,
  70. <a href="<?php print '../../' . $xml_filename; ?>">XML</a>
  71. </p>
  72. <!-- @deepaksomanadh: For displaying BLAST command details -->
  73. <table>
  74. <tr>
  75. <th>Input query sequence(s) </th>
  76. <th>Target Database selected </th>
  77. <th>BLAST command executed </th>
  78. <tr>
  79. <tr>
  80. <?php
  81. // get input sequences from job_data variable
  82. $query_def = $job_id_data['query_def'];
  83. echo "<td>";
  84. echo "<ol>";
  85. foreach($query_def as $row) {
  86. echo "<li>";
  87. echo $row . "</li>";
  88. }
  89. echo "</ol></td>";
  90. echo "<td>" . $job_id_data['db_name'] . "</td>"
  91. ?>
  92. <?php
  93. include_once("blast_align_image.php");
  94. //display the BLAST command without revealing the internal path
  95. $blast_cmd = $job_id_data['program'];
  96. foreach($job_id_data['options'] as $key => $value) {
  97. $blast_cmd .= ' -' . $key. ' ' . $value ;
  98. }
  99. print "<td>" . $blast_cmd . "</td>";
  100. ?>
  101. </table>
  102. <p>The following table summarizes the results of your BLAST.
  103. Click on a <strong>triangle </strong> on the left to see the alignment and a visualization of the hit,
  104. and click the <strong>target name </strong> to open a new window with a genome browser around this hit.</p>
  105. <?php
  106. include_once("blast_align_image.php");
  107. // Load the XML file
  108. $xml = simplexml_load_file($xml_filename);
  109. /**
  110. * We are using the drupal table theme functionality to create this listing
  111. * @see theme_table() for additional documentation
  112. */
  113. if ($xml) {
  114. // Specify the header of the table
  115. $header = array(
  116. 'arrow-col' => array('data' => '', 'class' => array('arrow-col')),
  117. 'number' => array('data' => '#', 'class' => array('number')),
  118. 'query' => array('data' => 'Query Name (Click for alignment & visualization)', 'class' => array('query')),
  119. 'hit' => array('data' => 'Target Name', 'class' => array('hit')),
  120. 'evalue' => array('data' => 'E-Value', 'class' => array('evalue')),
  121. );
  122. $rows = array();
  123. $count = 0;
  124. // Parse the BLAST XML to generate the rows of the table
  125. // where each hit results in two rows in the table: 1) A summary of the query/hit and
  126. // significance and 2) additional information including the alignment
  127. foreach ($xml->{'BlastOutput_iterations'}->children() as $iteration) {
  128. $children_count = $iteration->{'Iteration_hits'}->children()->count();
  129. //@deepaksomanadh: Code added for BLAST visualization
  130. // parameters that need to be passed for BLAST image generation
  131. $target_name = '';
  132. $q_name = $xml->{'BlastOutput_query-def'};
  133. $query_size = $xml->{'BlastOutput_query-len'};
  134. $target_size = $iteration->{'Iteration_stat'}->{'Statistics'}->{'Statistics_db-len'};
  135. if ($children_count != 0) {
  136. foreach ($iteration->{'Iteration_hits'}->children() as $hit) {
  137. if (is_object($hit)) {
  138. $count +=1;
  139. $zebra_class = ($count % 2 == 0) ? 'even' : 'odd';
  140. $no_hits = FALSE;
  141. // RETRIEVE INFO
  142. $hit_name = (preg_match('/BL_ORD_ID/', $hit->{'Hit_id'})) ? $hit->{'Hit_def'} : $hit->{'Hit_id'};
  143. $score = $hit->{'Hit_hsps'}->{'Hsp'}->{'Hsp_score'};
  144. $evalue = $hit->{'Hit_hsps'}->{'Hsp'}->{'Hsp_evalue'};
  145. $query_name = $iteration->{'Iteration_query-def'};
  146. // Round e-val to two decimal values
  147. $rounded_evalue = '';
  148. if (strpos($evalue,'e') != false) {
  149. $evalue_split = explode('e', $evalue);
  150. $rounded_evalue = round($evalue_split[0], 2, PHP_ROUND_HALF_EVEN);
  151. $rounded_evalue .= 'e' . $evalue_split[1];
  152. }
  153. else {
  154. $rounded_evalue = $evalue;
  155. }
  156. // ALIGNMENT ROW (collapsed by default)
  157. // Process HSPs
  158. // @deepaksomanadh: Code added for BLAST visualization
  159. // hit array and corresponding bit scores
  160. // hits=4263001_4262263_1_742;4260037_4259524_895_1411;&scores=722;473;
  161. $HSPs = array();
  162. $track_start = INF;
  163. $track_end = -1;
  164. $hsps_range = '';
  165. $hit_hsps = '';
  166. $hit_hsp_score = '';
  167. $target_size = $hit->{'Hit_len'};
  168. foreach ($hit->{'Hit_hsps'}->children() as $hsp_xml) {
  169. $HSPs[] = (array) $hsp_xml;
  170. if ($track_start > $hsp_xml->{'Hsp_hit-from'}) {
  171. $track_start = $hsp_xml->{'Hsp_hit-from'} . "";
  172. }
  173. if ($track_end < $hsp_xml->{'Hsp_hit-to'}) {
  174. $track_end = $hsp_xml->{'Hsp_hit-to'} . "";
  175. }
  176. }
  177. $range_start = (int) $track_start - 50000;
  178. $range_end = (int) $track_end + 50000;
  179. if ($range_start < 1)
  180. $range_start = 1;
  181. // For BLAST visualization
  182. $target_size = $hit->{'Hit_len'};
  183. foreach ($hit->{'Hit_hsps'}->children() as $hsp_xml) {
  184. $hit_hsps .= $hsp_xml->{'Hsp_hit-from'} . '_' .
  185. $hsp_xml->{'Hsp_hit-to'} . '_' .
  186. $hsp_xml->{'Hsp_query-from'} . '_' . $hsp_xml->{'Hsp_query-to'} .
  187. ';';
  188. $Hsp_bit_score .= $hsp_xml->{'Hsp_bit-score'} .';';
  189. }
  190. // SUMMARY ROW
  191. // If the id is of the form gnl|BL_ORD_ID|### then the parseids flag
  192. // to makeblastdb did a really poor job. In this case we want to use
  193. // the def to provide the original FASTA header.
  194. // If our BLAST DB is configured to handle link-outs then use the
  195. // regex & URL prefix provided to create one.
  196. //eksc- linkout vs gbrowse
  197. $hit_name = $hit->{'Hit_def'};
  198. $query_name = $iteration->{'Iteration_query-def'};
  199. // ***** Future modification ***** The gbrowse_url can be extracted from Tripal Database table
  200. if(preg_match('/.*(aradu).*/i', $hit_name) == 1) {
  201. $gbrowse_url = 'gbrowse_aradu1.0';
  202. }
  203. else if(preg_match('/.*(araip).*/i', $hit_name) == 1) {
  204. $gbrowse_url = 'gbrowse_araip1.0';
  205. } else if(preg_match('/.*(phytozome).*/i', $hit_name) == 1) {
  206. $gbrowse_url = 'http://legumeinfo.org/chado_phylotree/';
  207. } else {
  208. // Not existing in available GBrowse tracks
  209. $gbrowse_url = null;
  210. }
  211. // $hit_name_url = l($linkout_urlprefix . $linkout_match[1],
  212. // array('attributes' => array('target' => '_blank'))
  213. // );
  214. // Link out functionality to GBrowse
  215. if($gbrowse_url == null) {
  216. // Not a valid hit. Hence, No link outs to GBrowse and the hit name is displayed.
  217. $hit_name_url = $hit_name;
  218. }
  219. else {
  220. // Link out is possible for this hit
  221. // Check if our BLAST DB is configured to handle link-outs then use the
  222. // regex & URL prefix provided to create one.
  223. // Then, check if the db is configured to handle linkouts
  224. // For alias targets
  225. if ($linkout) {
  226. // For CDS/protein alias targets
  227. if(preg_match("/http:/", $gbrowse_url) == 1) {
  228. $hit_url = $gbrowse_url . $hit_name ;
  229. $hit_name_url = l($hit_name, $hit_url, array('attributes' => array('target' => '_blank')));
  230. }
  231. else if (preg_match($linkout_regex, $hit_name, $linkout_match) == 1) {
  232. $hit_name = $linkout_match[1];
  233. // matches found
  234. $hit_url = $GLOBALS['base_url'] . '/' . $gbrowse_url . '?' . 'query=q=';
  235. $hit_url .= $hit_name . ';h_feat=' . $iteration->{'Iteration_query-ID'};
  236. $hit_name_url = l($hit_name, $hit_url, array('attributes' => array('target' => '_blank')));
  237. }
  238. else {
  239. // No matches for regex. Hence, linkouts not possible
  240. $hit_name_url = $hit_name;
  241. }
  242. }
  243. else {
  244. // For Genome targets
  245. $hit_url = $GLOBALS['base_url'] . '/' . $gbrowse_url . '?' . 'query=' . 'start=' . $range_start . ';' . 'stop=' .
  246. $range_end . ';' . 'ref=' . $hit_name . ';' . 'add=' . $hit_name . '+' . 'BLAST+' . $iteration->{'Iteration_query-ID'} . '+' . $hsps_range . ';h_feat=' . $iteration->{'Iteration_query-ID'} ;
  247. $hit_name_url = l($hit_name, $hit_url, array('attributes' => array('target' => '_blank')));
  248. }
  249. }// end of GBrowse functionality
  250. /* eksc- linkout vs gbrowse
  251. if ($linkout) {
  252. if (preg_match($linkout_regex, $hit_name, $linkout_match)) {
  253. $linkout_id = $linkout_match[1];
  254. $hit->{'linkout_id'} = $linkout_id;
  255. $hit->{'hit_name'} = $hit_name;
  256. $hit_url = call_user_func(
  257. $url_function,
  258. $linkout_urlprefix,
  259. $hit,
  260. array(
  261. 'query_name' => $query_name,
  262. 'score' => $score,
  263. 'e-value' => $evalue,
  264. 'HSPs' => $HSPs
  265. )
  266. );
  267. if ($hit_url) {
  268. $hit_name = l(
  269. $linkout_id,
  270. $hit_url,
  271. array('attributes' => array('target' => '_blank'))
  272. );
  273. }
  274. }
  275. }
  276. */
  277. //@deepaksomanadh: Code added for BLAST visualization
  278. // get the image and display
  279. $hit_img = generateImage($target_name, $Hsp_bit_score, $hit_hsps, $target_size, $query_size, $q_name, $hit_name);
  280. ob_start(); // Start buffering the output
  281. imagepng($hit_img, null, 0, PNG_NO_FILTER);
  282. $b64 = base64_encode(ob_get_contents()); // Get what we've just outputted and base64 it
  283. imagedestroy($hit_img);
  284. ob_end_clean();
  285. // Print the HTML tag with the image embedded
  286. $hit_img = '<h4><strong> Hit Visualization </strong></h4> <br><img src="data:image/png;base64,'.$b64.'"/>';
  287. $row = array(
  288. 'data' => array(
  289. 'arrow-col' => array('data' => '<div class="arrow"></div>', 'class' => array('arrow-col')),
  290. 'number' => array('data' => $count, 'class' => array('number')),
  291. 'query' => array('data' => $query_name, 'class' => array('query')),
  292. 'hit' => array('data' => $hit_name, 'class' => array('hit')),
  293. 'evalue' => array('data' => $rounded_evalue, 'class' => array('evalue')),
  294. 'arrow-col' => array('data' => '<div class="arrow"></div>', 'class' => array('arrow-col'))
  295. ),
  296. 'class' => array('result-summary')
  297. );
  298. $rows[] = $row;
  299. // ALIGNMENT ROW (collapsed by default)
  300. // Process HSPs
  301. $row = array(
  302. 'data' => array(
  303. 'arrow' => '',
  304. 'number' => '',
  305. 'query' => array(
  306. 'data' => theme('blast_report_alignment_row', array('HSPs' => $HSPs)),
  307. // 'colspan' => 4,
  308. ),
  309. 'hit' => array(
  310. 'data' => $hit_img,
  311. 'colspan' => 3,
  312. ),
  313. ),
  314. 'class' => array('alignment-row', $zebra_class),
  315. 'no_striping' => TRUE
  316. );
  317. $rows[] = $row;
  318. }// end of if - checks $hit
  319. } //end of foreach - iteration_hits
  320. } // end of if - check for iteration_hits
  321. else {
  322. // Currently where the "no results" is added.
  323. $query_name = $iteration->{'Iteration_query-def'};
  324. $query_with_no_hits[] = $query_name;
  325. }// end of else
  326. }//end of foreach - BlastOutput_iterations
  327. if ($no_hits) {
  328. print '<p class="no-hits-message">No results found.</p>';
  329. }
  330. else {
  331. // We want to warn the user if some of their query sequences had no hits.
  332. if (!empty($query_with_no_hits)) {
  333. print '<p class="no-hits-message">Some of your query sequences did not '
  334. . 'match to the database/template. They are: '
  335. . implode(', ', $query_with_no_hits) . '.</p>';
  336. }
  337. // Actually print the table.
  338. if (!empty($rows)) {
  339. print theme('table', array(
  340. 'header' => $header,
  341. 'rows' => $rows,
  342. 'attributes' => array('id' => 'blast_report'),
  343. ));
  344. }
  345. }
  346. }
  347. else {
  348. drupal_set_title('BLAST: Error Encountered');
  349. print '<p>We encountered an error and are unable to load your BLAST results.</p>';
  350. }
  351. ?>
  352. <p> <!-- @deepaksomanadh: Building the edit and resubmit URL -->
  353. <a style ="align:center" href="<?php print '../../'. $job_id_data['job_url'] . '?jid=' . base64_encode($job_id) ?>">Edit this query and re-submit</a>
  354. </p>
  355. <strong> Recent Jobs </strong>
  356. <ol>
  357. <?php
  358. $sid = session_id();
  359. $jobs = $_SESSION['all_jobs'][$sid];
  360. foreach ( $jobs as $job) {
  361. echo "<li>";
  362. $q_def = !isset($job['query_defs'][0]) ? "Query" : $job['query_defs'][0];
  363. echo "<a href='" . "../../" . $job['job_output_url'] ."' >"
  364. . $q_def ."->". $job['program'] . "</a>";
  365. echo "</li>";
  366. }
  367. ?>
  368. </ol>