Bladeren bron

Changes to the blast report page including clean-up of the hit vis. code

Lacey Sanderson 9 jaren geleden
bovenliggende
commit
e2339248f7

+ 221 - 0
api/blast_ui.api.inc

@@ -107,6 +107,7 @@ function get_blast_database_options($type) {
  *   BLAST job (ie: 250)
  */
 function run_BLAST_tripal_job($program, $query, $database, $output_filestub, $options, $job_id = NULL) {
+
   $output_file = file_directory_temp() .  DIRECTORY_SEPARATOR . $output_filestub . '.blast.asn';
   $output_dir = variable_get('file_public_path', conf_path() . '/files') 
               . DIRECTORY_SEPARATOR . 'tripal' . DIRECTORY_SEPARATOR . 'tripal_blast';
@@ -338,4 +339,224 @@ function get_recent_blast_jobs($programs = array()) {
   else {
     return array();
   }
+}
+
+/**
+ * Generate an image of HSPs for a given hit.
+ *          
+ * history:
+ *    09/23/10  Carson  created
+ *    04/16/12  eksc    adapted into POPcorn code
+ *    03/12/15  deepak  Adapted code into Tripal BLAST
+ *    10/23/15  lacey   Fixed deepak's code to be suitable for Drupal.
+ *
+ * @param $acc
+ *    target name
+ * @param $name
+ *    query name, false if none
+ * @param $tsize
+ *    target size
+ * @param $qsize
+ *    query size
+ * @param $hits
+ *    each hit represented in URL as: targetstart_targetend_hspstart_hspend;
+ * @param $score
+ *    score for each hit
+ *
+ * @returm
+ *    A base64 encoded image representing the hit information.
+ */
+function generate_blast_hit_image($acc = '', $scores, $hits, $tsize, $qsize, $name, $hit_name) {
+  $tok = strtok($hits, ";");
+  $b_hits = Array();
+  while ($tok !== false) {
+    $b_hits[] = $tok;
+    $tok = strtok(";");
+  }
+
+  // extract score information from score param
+  $tokscr = strtok($scores, ";");
+  $b_scores = Array();
+  while ($tokscr !== false) {
+   $b_scores[] = $tokscr;
+   $tokscr = strtok(";");
+  }
+
+  // image measurements
+  $height = 200 + (count($b_hits) * 16);
+  $width  = 520;
+
+  $img = imagecreatetruecolor($width, $height);
+
+  $white      = imagecolorallocate($img, 255, 255, 255);
+  $black      = imagecolorallocate($img, 0, 0, 0);
+  $darkgray   = imagecolorallocate($img, 100, 100, 100);
+  $strong     = imagecolorallocatealpha($img, 202, 0, 0, 15);
+  $moderate   = imagecolorallocatealpha($img, 204, 102, 0, 20);
+  $present    = imagecolorallocatealpha($img, 204, 204, 0, 35);
+  $weak       = imagecolorallocatealpha($img, 102, 204, 0, 50);
+  $gray       = imagecolorallocate($img, 190, 190, 190);
+  $lightgray  = $white; //imagecolorallocate($img, 230, 230, 230);
+
+  imagefill($img, 0, 0, $lightgray);
+
+  // Target coordinates
+  $maxlength = 300;
+  $t_length = ($tsize > $qsize) 
+                ? $maxlength : $maxlength - 50;
+  $q_length = ($qsize > $tsize) 
+                ? $maxlength : $maxlength - 50;
+              
+  $tnormal = $t_length / $tsize;
+  $qnormal = $q_length / $qsize; 
+
+  $t_ystart = 30;
+  $t_yend   = $t_ystart + 20;
+
+  $t_xstart = 50;
+  $t_xend   = $t_xstart + $t_length;
+  $t_center = $t_xstart + ($t_length / 2);
+
+  // Target labels
+  $warn = '"'. $hit_name . '"';
+  imagestring($img, 5, $t_xstart, $t_ystart-20, $acc.$warn, $black);
+  imagestring($img, 3, 5, $t_ystart+2, "Target", $black);
+
+  // Draw bar representing target
+  imagefilledrectangle($img, $t_xstart, $t_ystart, $t_xend, $t_yend, $gray);
+  imagerectangle($img, $t_xstart, $t_ystart, $t_xend, $t_yend, $darkgray);
+
+  // query coordinates
+  $q_maxheight = 250;
+  $q_ystart = $t_yend + 100;
+  $q_yend = $q_ystart + 20;
+
+  $q_xstart = $t_center - $q_length / 2;
+  $q_xend = $q_xstart + $q_length;
+
+  $q_center = ($q_xend + $q_xstart) / 2;
+  $q_xwidth = $q_xend - $q_xstart;
+
+  // Query labels
+  imagestring($img, 5, $q_xstart, $q_yend+2, $name, $black);
+  imagestring($img, 3, $q_xstart, $q_ystart+2, 'Query', $black);
+
+  // Draw bar representing query
+  imagefilledrectangle($img, $q_xstart, $q_ystart, $q_xend, $q_yend, $gray);
+  imagerectangle($img ,$q_xstart, $q_ystart, $q_xend, $q_yend, $darkgray);
+
+  // HSP bars will start here
+  $hsp_bary = $q_yend + 20;
+
+  // Draw solids for HSP alignments
+  for ($ii=count($b_hits)-1; $ii>=0; $ii--) {
+    // alignment 
+
+   $cur_hit = $b_hits[$ii];
+   $cur_score = intval($b_scores[$ii]);
+ 
+   // set color according to score
+   $cur_color = $darkgray;
+   if ($cur_score > 200) { 
+     $cur_color = $strong;
+   } 
+   else if ($cur_score > 80 && $cur_score <= 200) { 
+     $cur_color = $moderate;
+   } 
+   else if ($cur_score > 50 && $cur_score <= 80) { 
+     $cur_color = $present;
+   } 
+   else if ($cur_score > 40 && $cur_score <= 50) { 
+     $cur_color = $weak;
+   } 
+
+   $t_start = $tnormal *  intval(strtok($cur_hit, "_")) + $t_xstart;
+    $t_end = $tnormal *  intval(strtok("_")) + $t_xstart;
+    $q_start = $qnormal * intval(strtok("_")) + $q_xstart;
+    $q_end = $qnormal *  intval(strtok("_")) + $q_xstart;
+
+    $hit1_array = array($t_start, $t_yend, $t_end, $t_yend, $q_end, 
+                        $q_ystart, $q_start, $q_ystart);
+
+   // HSP coords
+    imagefilledpolygon($img, $hit1_array, 4, $cur_color);
+
+  }//each hit
+
+  // Draw lines over fills for HSP alignments
+  for ($ii=0; $ii<count($b_hits); $ii++) {
+   // alignment 
+ 
+   $cur_hit = $b_hits[$ii];
+   $t_start = $tnormal *  intval(strtok($cur_hit, "_")) + $t_xstart;
+    $t_end = $tnormal *  intval(strtok("_")) + $t_xstart;
+    $q_start = $qnormal * intval(strtok("_")) + $q_xstart;
+    $q_end = $qnormal *  intval(strtok("_")) + $q_xstart;
+   
+   $hit1_array = array($t_start, $t_yend, $t_end, $t_yend, $q_end, $q_ystart,
+                       $q_start, $q_ystart,);
+
+   imagerectangle($img, $t_start, $t_ystart, $t_end, $t_yend, $black);
+   imagerectangle($img, $q_start, $q_ystart, $q_end, $q_yend, $black);
+   imagepolygon ($img, $hit1_array, 4, $black);
+
+    // show HSP
+  
+   imagestring($img, 3, 2, $hsp_bary, ($acc ."HSP" . ($ii + 1)), $black);
+
+   $cur_score = intval($b_scores[$ii]);
+ 
+   // set color according to score
+   $cur_color = $darkgray;
+   if ($cur_score > 200) { 
+     $cur_color = $strong;
+   } 
+   else if ($cur_score > 80 && $cur_score <= 200) { 
+     $cur_color = $moderate;
+   } 
+   else if ($cur_score > 50 && $cur_score <= 80) { 
+     $cur_color = $present;
+   } 
+   else if ($cur_score > 40 && $cur_score <= 50) { 
+     $cur_color = $weak;
+   }
+ 
+   imagefilledrectangle($img, $q_start, $hsp_bary, $q_end, $hsp_bary+10, $cur_color);
+    $hsp_bary += 15;
+  }//each hit
+
+  // Draw the key
+
+  $xchart = 390;
+  $ychart = 10;
+  $fontsize = 4;
+  $yinc = 20;
+  $ywidth = 7;
+  $xinc = 10;
+
+  imagestring($img, 5, $xchart, $ychart - 5, "Bit Scores", $black);
+
+  imagestring($img, $fontsize, $xchart + $yinc + $xinc,$ychart + ($yinc * 1) + $ywidth, ">= 200" , $black);
+  imagestring($img, $fontsize, $xchart + $yinc + $xinc,$ychart + ($yinc * 2) + $ywidth, "80 - 200" , $black);
+  imagestring($img, $fontsize, $xchart + $yinc + $xinc,$ychart + ($yinc * 3) + $ywidth, "50 - 80" , $black);
+  imagestring($img, $fontsize, $xchart + $yinc + $xinc,$ychart + ($yinc * 4) + $ywidth, "40 - 50" , $black);
+  imagestring($img, $fontsize, $xchart + $yinc + $xinc,$ychart + ($yinc * 5) + $ywidth, "< 40" , $black);
+
+  imagefilledRectangle($img, $xchart, $ychart + ($yinc * 1) + $xinc, $xchart + $yinc, $ychart + ($yinc * 2), $strong);
+  imagefilledRectangle($img, $xchart, $ychart + ($yinc * 2) + $xinc, $xchart + $yinc, $ychart + ($yinc * 3), $moderate);
+  imagefilledRectangle($img, $xchart, $ychart + ($yinc * 3) + $xinc, $xchart + $yinc, $ychart + ($yinc * 4), $present);
+  imagefilledRectangle($img, $xchart, $ychart + ($yinc * 4) + $xinc, $xchart + $yinc, $ychart + ($yinc * 5), $weak);
+  imagefilledRectangle($img, $xchart, $ychart + ($yinc * 5) + $xinc, $xchart + $yinc, $ychart + ($yinc * 6), $darkgray);
+
+  // Now, we have a completed image resource and need to change it to an actual image
+  // that can be displayed. This is done using imagepng() but unfortuatly that function 
+  // either saves the image to a file or outputs it directly to the screen. Thus, we use
+  // the following code to capture it and base64 encode it.
+  ob_start(); // Start buffering the output
+  imagepng($img, null, 0, PNG_NO_FILTER);
+  $b64_img = base64_encode(ob_get_contents()); // Get what we've just outputted and base64 it
+  imagedestroy($img);
+  ob_end_clean();
+   
+  return $b64_img;
 }

+ 1 - 0
includes/blast_ui.form_per_program.inc

@@ -99,6 +99,7 @@ function blast_ui_per_blast_program_form($form, $form_state) {
       'header' => array('Query Information', 'Search Target', 'Date Requested', ''),
       'rows' => array(),
       'attributes' => array('class' => array('tripal-blast', 'recent-jobs')),
+      'sticky' => TRUE,
     );
       
     foreach ($recent_jobs as $job) {

+ 0 - 208
theme/blast_align_image.php

@@ -1,208 +0,0 @@
-<?PHP
-/* file: blast_align_image.php
- * 
- * purpose: generate an image of HSPs for a given target
- *          
- *          URL paramters:
- *            acc   - target name
- *            name  - query name, false if none
- *            tsize - target size
- *            qsize - query size
- *            hits  - each hit represented in URL as: 
- *                  targetstart_targetend_hspstart_hspend;
- *            score - score for each hit
- *                  
- * Example: <url>blast_align_image.php?acc=chr2&name=query1&tsize=237068873&qsize=1411&hits=4263001_4262263_1_742;4260037_4259524_895_1411;4260405_4260248_740_897;192158716_192158843_612_742;&scores=722;473;155;51;
- * 
- * history:
- *    09/23/10  Carson  created
- *    04/16/12  eksc    adapted into POPcorn code
- *    03/12/15  deepak  Adapted code into Tripal BLAST
- */
- 
-// extract hit information from hit param
-function generateImage($acc = '', $scores, $hits, $tsize, $qsize, $name, $hit_name) {
-   $tok = strtok($hits, ";");
-   $b_hits = Array();
-   while ($tok !== false) {
-      $b_hits[] = $tok;
-      $tok = strtok(";");
-   }
-
-   // extract score information from score param
-   $tokscr = strtok($scores, ";");
-   $b_scores = Array();
-   while ($tokscr !== false) {
-     $b_scores[] = $tokscr;
-     $tokscr = strtok(";");
-   }
-
-   // image measurements
-   $height = 200 + (count($b_hits) * 16);
-   $width  = 520;
-
-   $img = imagecreatetruecolor($width, $height);
-   
-   $white      = imagecolorallocate($img, 255, 255, 255);
-   $black      = imagecolorallocate($img, 0, 0, 0);
-   $darkgray   = imagecolorallocate($img, 100, 100, 100);
-   $strong     = imagecolorallocatealpha($img, 202, 0, 0, 15);
-   $moderate   = imagecolorallocatealpha($img, 204, 102, 0, 20);
-   $present    = imagecolorallocatealpha($img, 204, 204, 0, 35);
-   $weak       = imagecolorallocatealpha($img, 102, 204, 0, 50);
-   $gray       = imagecolorallocate($img, 190, 190, 190);
-   $lightgray  = imagecolorallocate($img, 230, 230, 230);
-   
-   imagefill($img, 0, 0, $lightgray);
-   
-   // Target coordinates
-   $maxlength = 300;
-   $t_length = ($tsize > $qsize) 
-                  ? $maxlength : $maxlength - 50;
-   $q_length = ($qsize > $tsize) 
-                  ? $maxlength : $maxlength - 50;
-                  
-   $tnormal = $t_length / $tsize;
-   $qnormal = $q_length / $qsize; 
-  
-   $t_ystart = 30;
-   $t_yend   = $t_ystart + 20;
-  
-   $t_xstart = 50;
-   $t_xend   = $t_xstart + $t_length;
-   $t_center = $t_xstart + ($t_length / 2);
-   
-   // Target labels
-   $warn = '"'. $hit_name . '"';
-   imagestring($img, 5, $t_xstart, $t_ystart-20, $acc.$warn, $black);
-   imagestring($img, 3, 5, $t_ystart+2, "Target", $black);
-   
-   // Draw bar representing target
-   imagefilledrectangle($img, $t_xstart, $t_ystart, $t_xend, $t_yend, $gray);
-   imagerectangle($img, $t_xstart, $t_ystart, $t_xend, $t_yend, $darkgray);
-   
-   // query coordinates
-   $q_maxheight = 250;
-   $q_ystart = $t_yend + 100;
-   $q_yend = $q_ystart + 20;
-  
-   $q_xstart = $t_center - $q_length / 2;
-   $q_xend = $q_xstart + $q_length;
-
-   $q_center = ($q_xend + $q_xstart) / 2;
-   $q_xwidth = $q_xend - $q_xstart;
-
-   // Query labels
-   imagestring($img, 5, $q_xstart, $q_yend+2, $name, $black);
-   imagestring($img, 3, $q_xstart, $q_ystart+2, 'Query', $black);
-   
-   // Draw bar representing query
-   imagefilledrectangle($img, $q_xstart, $q_ystart, $q_xend, $q_yend, $gray);
-   imagerectangle($img ,$q_xstart, $q_ystart, $q_xend, $q_yend, $darkgray);
-   
-   // HSP bars will start here
-   $hsp_bary = $q_yend + 20;
-   
-   // Draw solids for HSP alignments
-   for ($ii=count($b_hits)-1; $ii>=0; $ii--) {
-      // alignment 
-  
-     $cur_hit = $b_hits[$ii];
-     $cur_score = intval($b_scores[$ii]);
-     
-     // set color according to score
-     $cur_color = $darkgray;
-     if ($cur_score > 200) { 
-       $cur_color = $strong;
-     } 
-     else if ($cur_score > 80 && $cur_score <= 200) { 
-       $cur_color = $moderate;
-     } 
-     else if ($cur_score > 50 && $cur_score <= 80) { 
-       $cur_color = $present;
-     } 
-     else if ($cur_score > 40 && $cur_score <= 50) { 
-       $cur_color = $weak;
-     } 
-  
-     $t_start = $tnormal *  intval(strtok($cur_hit, "_")) + $t_xstart;
-      $t_end = $tnormal *  intval(strtok("_")) + $t_xstart;
-      $q_start = $qnormal * intval(strtok("_")) + $q_xstart;
-      $q_end = $qnormal *  intval(strtok("_")) + $q_xstart;
-    
-      $hit1_array = array($t_start, $t_yend, $t_end, $t_yend, $q_end, 
-                          $q_ystart, $q_start, $q_ystart);
-
-     // HSP coords
-      imagefilledpolygon($img, $hit1_array, 4, $cur_color);
-  
-   }//each hit
-
-   // Draw lines over fills for HSP alignments
-   for ($ii=0; $ii<count($b_hits); $ii++) {
-     // alignment 
-     
-     $cur_hit = $b_hits[$ii];
-     $t_start = $tnormal *  intval(strtok($cur_hit, "_")) + $t_xstart;
-      $t_end = $tnormal *  intval(strtok("_")) + $t_xstart;
-      $q_start = $qnormal * intval(strtok("_")) + $q_xstart;
-      $q_end = $qnormal *  intval(strtok("_")) + $q_xstart;
-       
-     $hit1_array = array($t_start, $t_yend, $t_end, $t_yend, $q_end, $q_ystart,
-                         $q_start, $q_ystart,);
-   
-     imagerectangle($img, $t_start, $t_ystart, $t_end, $t_yend, $black);
-     imagerectangle($img, $q_start, $q_ystart, $q_end, $q_yend, $black);
-     imagepolygon ($img, $hit1_array, 4, $black);
-
-      // show HSP
-      
-     imagestring($img, 3, 2, $hsp_bary, ($acc ."HSP" . ($ii + 1)), $black);
-
-     $cur_score = intval($b_scores[$ii]);
-     
-     // set color according to score
-     $cur_color = $darkgray;
-     if ($cur_score > 200) { 
-       $cur_color = $strong;
-     } 
-     else if ($cur_score > 80 && $cur_score <= 200) { 
-       $cur_color = $moderate;
-     } 
-     else if ($cur_score > 50 && $cur_score <= 80) { 
-       $cur_color = $present;
-     } 
-     else if ($cur_score > 40 && $cur_score <= 50) { 
-       $cur_color = $weak;
-     }
-     
-     imagefilledrectangle($img, $q_start, $hsp_bary, $q_end, $hsp_bary+10, $cur_color);
-      $hsp_bary += 15;
-   }//each hit
-
-   // Draw the key
-   
-   $xchart = 390;
-   $ychart = 10;
-   $fontsize = 4;
-   $yinc = 20;
-   $ywidth = 7;
-   $xinc = 10;
-   
-   imagestring($img, 5, $xchart, $ychart - 5, "Bit Scores", $black);
-   
-   imagestring($img, $fontsize, $xchart + $yinc + $xinc,$ychart + ($yinc * 1) + $ywidth, ">= 200" , $black);
-   imagestring($img, $fontsize, $xchart + $yinc + $xinc,$ychart + ($yinc * 2) + $ywidth, "80 - 200" , $black);
-   imagestring($img, $fontsize, $xchart + $yinc + $xinc,$ychart + ($yinc * 3) + $ywidth, "50 - 80" , $black);
-   imagestring($img, $fontsize, $xchart + $yinc + $xinc,$ychart + ($yinc * 4) + $ywidth, "40 - 50" , $black);
-   imagestring($img, $fontsize, $xchart + $yinc + $xinc,$ychart + ($yinc * 5) + $ywidth, "< 40" , $black);
-   
-   imagefilledRectangle($img, $xchart, $ychart + ($yinc * 1) + $xinc, $xchart + $yinc, $ychart + ($yinc * 2), $strong);
-   imagefilledRectangle($img, $xchart, $ychart + ($yinc * 2) + $xinc, $xchart + $yinc, $ychart + ($yinc * 3), $moderate);
-   imagefilledRectangle($img, $xchart, $ychart + ($yinc * 3) + $xinc, $xchart + $yinc, $ychart + ($yinc * 4), $present);
-   imagefilledRectangle($img, $xchart, $ychart + ($yinc * 4) + $xinc, $xchart + $yinc, $ychart + ($yinc * 5), $weak);
-   imagefilledRectangle($img, $xchart, $ychart + ($yinc * 5) + $xinc, $xchart + $yinc, $ychart + ($yinc * 6), $darkgray);
-   
-   return $img;
-}
-?>

+ 1 - 0
theme/blast_nucleotide_user_menupage.tpl.php

@@ -79,6 +79,7 @@ local alignment search tool. J. Mol. Biol., 215, 403–410.</blockquote>
       'header' => array('Query Information', 'Search Target', 'Date Requested', ''),
       'rows' => array(),
       'attributes' => array('class' => array('tripal-blast', 'recent-jobs')),
+      'sticky' => FALSE
     );
   
     foreach ($recent_jobs as $job) {

+ 1 - 0
theme/blast_protein_user_menupage.tpl.php

@@ -78,6 +78,7 @@ local alignment search tool. J. Mol. Biol., 215, 403–410.</blockquote>
       'header' => array('Query Information', 'Search Target', 'Date Requested', ''),
       'rows' => array(),
       'attributes' => array('class' => array('tripal-blast', 'recent-jobs')),
+      'sticky' => FALSE
     );
   
     foreach ($recent_jobs as $job) {

+ 46 - 70
theme/blast_report.tpl.php

@@ -74,52 +74,30 @@ $no_hits = TRUE;
 }
 </style>
 
-<p><strong>Download</strong>:
-  <a href="<?php print '../../' . $html_filename; ?>">Alignment</a>,
-  <a href="<?php print '../../' . $tsv_filename; ?>">Tab-Delimited</a>,
-  <a href="<?php print '../../' . $xml_filename; ?>">XML</a>
-</p>
-
-<!--  @deepaksomanadh: For displaying BLAST command details -->
-<table>
-<tr>
-  <th>Input query sequence(s) </th>
-  <th>Target Database selected </th>
-  <th>BLAST command executed </th>
-<tr>
-<tr>
-<?php 
-  // get input sequences from job_data variable
-  $query_def = $job_id_data['query_def'];
-  echo "<td>";
-  echo "<ol>";
-  foreach($query_def as $row) {
-    echo "<li>";    
-    echo  $row . "</li>";
-  }
-  echo "</ol></td>";
-  echo "<td>" .   $job_id_data['db_name'] . "</td>";
- 
-  include_once("blast_align_image.php");
- 
-  //display the BLAST command without revealing the internal path
-  $blast_cmd = $job_id_data['program'];
-  
-  foreach($job_id_data['options'] as $key => $value) {
-      $blast_cmd .= ' -' . $key. ' ' . $value ;
-  }
-  print "<td>" . $blast_cmd . "</td>";  
- ?>
-</table>
-
-<p>The following table summarizes the results of your BLAST. 
-Click on a <strong>triangle </strong> on the left to see the alignment and a visualization of the hit, 
-and click the <strong>target name </strong> to get more information about the target hit.</p>
+<div class="blast-report">
+
+<!-- Provide Information to the user about their blast job -->
+<div class="blast-job-info">
+<?php if($xml): ?>
+  <div class="blast-download-info"><strong>Download</strong>:
+    <a href="<?php print '../../' . $html_filename; ?>">Alignment</a>,
+    <a href="<?php print '../../' . $tsv_filename; ?>">Tab-Delimited</a>,
+    <a href="<?php print '../../' . $xml_filename; ?>">XML</a>
+  </div>
+<?php endif; ?>
+  <br />
+  <div class="blast-query-info"><strong>Query Information</strong>: 
+    <?php print $blast_job->display['query_info'];?></div>
+  <div class="blast-target-info"><strong>Search Target</strong>: 
+    <?php print $blast_job->display['target'];?></div>
+  <div class="blast-date-info"><strong>Submission Date</strong>: 
+    <?php print $blast_job->display['date'];?></div>
+  <div class="blast-cmd-info"><strong>BLAST Command executed</strong>: 
+    <?php print $blast_job->display['blast_cmd'];?></div>
+</div>
+<br />
 
 <?php
-include_once("blast_align_image.php");
-// Load the XML file
-$xml = simplexml_load_file($xml_filename);
 
 /**
  * We are using the drupal table theme functionality to create this listing
@@ -127,6 +105,13 @@ $xml = simplexml_load_file($xml_filename);
  */
 
 if ($xml) {
+?>
+
+<p>The following table summarizes the results of your BLAST. 
+Click on a <em>triangle </em> on the left to see the alignment and a visualization of the hit, 
+and click the <em>target name </em> to get more information about the target hit.</p>
+
+<?php
   // Specify the header of the table
   $header = array(
     'arrow-col' =>  array('data' => '', 'class' => array('arrow-col')),
@@ -206,7 +191,7 @@ if ($xml) {
 
           // For BLAST visualization 
           $target_size = $hit->{'Hit_len'};
-        
+          $Hsp_bit_score = '';
           foreach ($hit->{'Hit_hsps'}->children() as $hsp_xml) {
             $hit_hsps .=  $hsp_xml->{'Hsp_hit-from'} . '_' . 
                           $hsp_xml->{'Hsp_hit-to'} . '_' . 
@@ -223,6 +208,7 @@ if ($xml) {
           // If our BLAST DB is configured to handle link-outs then use the
           // regex & URL prefix provided to create one.
           $hit_name = $hit->{'Hit_def'};
+          $hit_name_short = (preg_match('/^([^\s]+)/', $hit_name, $matches)) ? $matches[1] : $hit_name;
           $query_name = $iteration->{'Iteration_query-def'};
  
           if ($linkout) {
@@ -271,17 +257,8 @@ if ($xml) {
 
           //@deepaksomanadh: Code added for BLAST visualization
           // get the image and display
-          $hit_img = generateImage($target_name, $Hsp_bit_score, $hit_hsps, 
-                                   $target_size, $query_size, $q_name, $hit_name);
-        
-          ob_start(); // Start buffering the output
-          imagepng($hit_img, null, 0, PNG_NO_FILTER);
-          $b64 = base64_encode(ob_get_contents()); // Get what we've just outputted and base64 it
-          imagedestroy($hit_img);
-          ob_end_clean();
-  
-          // Print the HTML tag with the image embedded
-          $hit_img = '<h4><strong> Hit Visualization </strong></h4> <br><img src="data:image/png;base64,'.$b64.'"/>';
+          $hit_img = generate_blast_hit_image($target_name, $Hsp_bit_score, $hit_hsps, 
+                                   $target_size, $query_size, $q_name, $hit_name_short);
           
           $row = array(
             'data' => array(
@@ -301,15 +278,9 @@ if ($xml) {
 
           $row = array(
             'data' => array(
-              'arrow' => '',
-              'number' => '',
-              'query' => array(
-                'data' => theme('blast_report_alignment_row', array('HSPs' => $HSPs)),
-              //  'colspan' => 4,
-              ),
-              'hit' => array(
-                'data' => $hit_img,
-                'colspan' => 3,
+              'arrow' => array(
+                'data' => theme('blast_report_alignment_row', array('HSPs' => $HSPs, 'hit_visualization' => $hit_img)),
+                'colspan' => 5,
               ),
             ),
             'class' => array('alignment-row', $zebra_class),
@@ -346,6 +317,7 @@ if ($xml) {
         'header' => $header,
         'rows' => $rows,
         'attributes' => array('id' => 'blast_report'),
+        'sticky' => FALSE
       ));
     }
   }//handle no hits
@@ -353,19 +325,22 @@ if ($xml) {
 
 else {
   drupal_set_title('BLAST: Error Encountered');
-  print '<p>We encountered an error and are unable to load your BLAST results.</p>';
+  print '<p class="blast-no-results">We encountered an error and are unable to load your BLAST results.</p>';
 }
 ?>
 
-<p> 
-  <a style ="align:center" href="<?php print '../../'. $job_id_data['job_url'] . '?jid=' . base64_encode($job_id) ?>">Edit this query and re-submit</a>  
-</p>
+<p><?php print l(
+  'Edit this query and re-submit', 
+  '../../' . $blast_job->form_options['job_url'],
+  array('query' => array('jid' => base64_encode($job_id))));
+?></p>
+</div>
 
 <!-- Recent Jobs -->
 <?php
 
   // Gets the list of recent jobs filtered to the current blast program (ie: blastn).
-  $recent_jobs = get_recent_blast_jobs();
+  
   if ($recent_jobs) {
   
     print '<h2>Recent Jobs</h2>';
@@ -374,6 +349,7 @@ else {
       'header' => array('Query Information', 'Search Target', 'Date Requested', ''),
       'rows' => array(),
       'attributes' => array('class' => array('tripal-blast', 'recent-jobs')),
+      'sticky' => FALSE
     );
   
     foreach ($recent_jobs as $job) {

+ 91 - 83
theme/blast_report_alignment_row.tpl.php

@@ -9,96 +9,104 @@
  */
 ?>
 
-<div class="title">Alignment</div>
+<div class="alignment-row-section hit-visualization" title="Your query sequence is shown at the bottom and the target sequence it aligned to is shown at the top. The shape connecting them indicates how much of the target and query are represented by the hit.">
+  <div class="title">Hit Visualization</div>
+  <img src="data:image/png;base64,<?php print $hit_visualization;?>"/>
+  <p>The image above shows the relationship between query and target for this 
+    particular BLAST hit.</p>
+</div>
+<div class="alignment-row-section alignment">
+  <div class="title">Alignment</div>
 
-<?php
-  foreach($HSPs as $hsp) {
-?>
+  <?php
+    foreach($HSPs as $hsp) {
+  ?>
 
-  <div class="hsp-title">HSP <?php print $hsp['Hsp_num']?></div>
-  <div class="alignment-metrics">
-    <span class="identity">
-      Identity=&nbsp;
-      <?php print $hsp['Hsp_identity']; ?>/<?php print $hsp['Hsp_align-len']; ?> (<?php print round($hsp['Hsp_identity']/$hsp['Hsp_align-len']*100, 2, PHP_ROUND_HALF_EVEN);?>%)
-    </span>,&nbsp;
-    <span class="positive">
-      Positive=&nbsp;
-      <?php print $hsp['Hsp_positive']; ?>/<?php print $hsp['Hsp_align-len']; ?> (<?php print round($hsp['Hsp_positive']/$hsp['Hsp_align-len']*100, 2, PHP_ROUND_HALF_EVEN);?>%)
-    </span>
-    <span class="coord-summary">
-      Query Matches <?php print $hsp['Hsp_query-from'] . ' to ' . $hsp['Hsp_query-to']; ?>
-      Hit Matches = <?php print $hsp['Hsp_hit-from'] . ' to ' . $hsp['Hsp_hit-to']; ?>
-    </span>
-  </div>
-  <div class="alignment">
-    <div class="alignment-row">
-      <?php 
-      // We want to display the alignment with a max 60 residues per line with line numbers indicated.
-      // First break up the strings.
-      $query = str_split($hsp['Hsp_qseq'], 60);
-      $matches = str_split($hsp['Hsp_midline'], 60);
-      $hit = str_split($hsp['Hsp_hseq'], 60);
-      // determine the max length of the coordinate string to use when padding.
-      $coord_length = strlen($hsp['Hsp_hit-from']) + 3;
-      $coord_length = (strlen($hsp['Hsp_query-to']) + 3 > $coord_length) ? strlen($hsp['Hsp_query-to']) + 3 : $coord_length;
+    <div class="hsp-title">HSP <?php print $hsp['Hsp_num']?></div>
+    <div class="alignment-metrics">
+      <span class="identity">
+        Identity=&nbsp;
+        <?php print $hsp['Hsp_identity']; ?>/<?php print $hsp['Hsp_align-len']; ?> (<?php print round($hsp['Hsp_identity']/$hsp['Hsp_align-len']*100, 2, PHP_ROUND_HALF_EVEN);?>%)
+      </span>,&nbsp;
+      <span class="positive">
+        Positive=&nbsp;
+        <?php print $hsp['Hsp_positive']; ?>/<?php print $hsp['Hsp_align-len']; ?> (<?php print round($hsp['Hsp_positive']/$hsp['Hsp_align-len']*100, 2, PHP_ROUND_HALF_EVEN);?>%)
+      </span>
+      <span class="coord-summary">
+        Query Matches <?php print $hsp['Hsp_query-from'] . ' to ' . $hsp['Hsp_query-to']; ?>
+        Hit Matches = <?php print $hsp['Hsp_hit-from'] . ' to ' . $hsp['Hsp_hit-to']; ?>
+      </span>
+    </div>
+    <div class="alignment">
+      <div class="alignment-row">
+        <?php 
+        // We want to display the alignment with a max 60 residues per line with line numbers indicated.
+        // First break up the strings.
+        $query = str_split($hsp['Hsp_qseq'], 60);
+        $matches = str_split($hsp['Hsp_midline'], 60);
+        $hit = str_split($hsp['Hsp_hseq'], 60);
+        // determine the max length of the coordinate string to use when padding.
+        $coord_length = strlen($hsp['Hsp_hit-from']) + 3;
+        $coord_length = (strlen($hsp['Hsp_query-to']) + 3 > $coord_length) ? strlen($hsp['Hsp_query-to']) + 3 : $coord_length;
 
-      // Now foreach chink determined above...
-      foreach (array_keys($query) as $k) {
-        // Determine the current coordinates.
-        $coord['qstart'] = $hsp['Hsp_query-from'] + ($k * 60);
-        $coord['qstart'] = ($k == 0) ? $coord['qstart'] : $coord['qstart'];
+        // Now foreach chink determined above...
+        foreach (array_keys($query) as $k) {
+          // Determine the current coordinates.
+          $coord['qstart'] = $hsp['Hsp_query-from'] + ($k * 60);
+          $coord['qstart'] = ($k == 0) ? $coord['qstart'] : $coord['qstart'];
         
-        // code added to fix the range issue
-        // Cordinates can increase or decrease
-        if($hsp['Hsp_hit-from'] < $hsp['Hsp_hit-to']) {
-            $coord['hstart'] = $hsp['Hsp_hit-from'] + ($k * 60);    
-          }
-          else {
-            $coord['hstart'] = $hsp['Hsp_hit-from'] - ($k * 60);
-          }
-//          $coord['qstop'] = $hsp['Hsp_query-from'] + (($k + 1) * 60) - 1;
-//          $coord['qstop'] = ($coord['qstop'] > $hsp['Hsp_query-to']) ? $hsp['Hsp_query-to'] : $coord['qstop'];
+          // code added to fix the range issue
+          // Cordinates can increase or decrease
+          if($hsp['Hsp_hit-from'] < $hsp['Hsp_hit-to']) {
+              $coord['hstart'] = $hsp['Hsp_hit-from'] + ($k * 60);    
+            }
+            else {
+              $coord['hstart'] = $hsp['Hsp_hit-from'] - ($k * 60);
+            }
+            $coord['qstop'] = $hsp['Hsp_query-from'] + (($k + 1) * 60) - 1;
+            $coord['qstop'] = ($coord['qstop'] > $hsp['Hsp_query-to']) ? $hsp['Hsp_query-to'] : $coord['qstop'];
       
-          if ($hsp['Hsp_hit-from'] < $hsp['Hsp_hit-to']) {
-            $coord['hstop'] = $hsp['Hsp_hit-from'] + (($k + 1) * 60) - 1;
-            $coord['hstop'] = ($coord['hstop'] > $hsp['Hsp_hit-to']) ? $hsp['Hsp_hit-to'] : $coord['hstop'];
+            if ($hsp['Hsp_hit-from'] < $hsp['Hsp_hit-to']) {
+              $coord['hstop'] = $hsp['Hsp_hit-from'] + (($k + 1) * 60) - 1;
+              $coord['hstop'] = ($coord['hstop'] > $hsp['Hsp_hit-to']) ? $hsp['Hsp_hit-to'] : $coord['hstop'];
           
-          }
-          else {
-            $coord['hstop'] = $hsp['Hsp_hit-from'] - (($k + 1) * 60) + 1;
-            $coord['hstop'] = ($coord['hstop'] < $hsp['Hsp_hit-to']) ? $hsp['Hsp_hit-to'] : $coord['hstop'];
-          }
+            }
+            else {
+              $coord['hstop'] = $hsp['Hsp_hit-from'] - (($k + 1) * 60) + 1;
+              $coord['hstop'] = ($coord['hstop'] < $hsp['Hsp_hit-to']) ? $hsp['Hsp_hit-to'] : $coord['hstop'];
+            }
           
-          // Pad these coordinates to ensure columned display.
-          foreach ($coord as $ck => $val) {
-            $pad_type = (preg_match('/start/', $ck)) ? STR_PAD_LEFT : STR_PAD_RIGHT;
-            $coord[$ck] = str_pad($val, $coord_length, '#', $pad_type);
-            $coord[$ck] =  str_replace('#', '&nbsp', $coord[$ck]);
-          }
-      ?>
-        <div class="alignment-subrow">
-          <div class="query">
-            <span class="alignment-title">Query:</span>&nbsp;&nbsp;
-            <span class="alignment-start-coord"><?php print $coord['qstart']; ?></span>
-            <span class="alignment-residues"><?php print $query[$k]; ?></span>
-            <span class="alignment-stop-coord"><?php print $coord['qstop']; ?></span>
-          </div>
-          <div class="matches">
-            <?php print  str_repeat('&nbsp;', 8); ?>
-            <?php print str_repeat('&nbsp;', $coord_length); ?>
-            <span class="alignment-residues"><?php print str_replace(' ', '&nbsp', $matches[$k]); ?></span>
+            // Pad these coordinates to ensure columned display.
+            foreach ($coord as $ck => $val) {
+              $pad_type = (preg_match('/start/', $ck)) ? STR_PAD_LEFT : STR_PAD_RIGHT;
+              $coord[$ck] = str_pad($val, $coord_length, '#', $pad_type);
+              $coord[$ck] =  str_replace('#', '&nbsp', $coord[$ck]);
+            }
+        ?>
+          <div class="alignment-subrow">
+            <div class="query">
+              <span class="alignment-title">Query:</span>&nbsp;&nbsp;
+              <span class="alignment-start-coord"><?php print $coord['qstart']; ?></span>
+              <span class="alignment-residues"><?php print $query[$k]; ?></span>
+              <span class="alignment-stop-coord"><?php print $coord['qstop']; ?></span>
+            </div>
+            <div class="matches">
+              <?php print  str_repeat('&nbsp;', 8); ?>
+              <?php print str_repeat('&nbsp;', $coord_length); ?>
+              <span class="alignment-residues"><?php print str_replace(' ', '&nbsp', $matches[$k]); ?></span>
+            </div>
+            <div class="hit">
+              <span class="alignment-title">Sbjct:</span>&nbsp;&nbsp;
+              <span class="alignment-start-coord"><?php print $coord['hstart']; ?></span>
+              <span class="alignment-residues"><?php print $hit[$k]; ?></span>
+              <span class="alignment-stop-coord"><?php print $coord['hstop']; ?></span>
+            </div>
           </div>
-          <div class="hit">
-            <span class="alignment-title">Sbjct:</span>&nbsp;&nbsp;
-            <span class="alignment-start-coord"><?php print $coord['hstart']; ?></span>
-            <span class="alignment-residues"><?php print $hit[$k]; ?></span>
-            <span class="alignment-stop-coord"><?php print $coord['hstop']; ?></span>
-          </div>
-        </div>
-      <?php } ?>
+        <?php } ?>
+      </div>
     </div>
-  </div>
 
-<?php
-  }
-?>
+  <?php
+    }
+  ?>
+</div>

+ 26 - 3
theme/blast_ui.theme.inc

@@ -24,6 +24,7 @@ function blast_ui_preprocess_show_blast_report(&$vars) {
   // Get the filename of the BLAST results
   $job = tripal_get_job($vars['job_id']);
   $job_args = unserialize($job->arguments);
+  
 //eksc- could stand better use of module settings and fewer hardcoded paths.
   $vars['xml_filename'] = variable_get('file_public_path', conf_path() . '/files') . '/tripal/tripal_blast/' . $job_args['output_filename'] . '.blast.xml';
   $vars['tsv_filename'] = variable_get('file_public_path', conf_path() . '/files') . '/tripal/tripal_blast/' . $job_args['output_filename'] . '.blast.tsv';
@@ -32,10 +33,32 @@ function blast_ui_preprocess_show_blast_report(&$vars) {
   // Add the blast database node.
   // This is needed for link-out functionality.
   $vars['blastdb'] = get_blast_database(array('path' => $job_args['database']));
-  //@deepaksomanadh: code added to use the persisted data in the template file.
-  $job_id = $vars['job_id'];
+  
+  // Get the recent job information.
+  $vars['recent_jobs'] = get_recent_blast_jobs();
+  
+  // Make job information available in the template.
+  $vars['blast_job'] = $job;
   $job_data = variable_get('job_data', '');
-  $vars['job_id_data'] = $job_data[$job_id];
+  if (isset($job_data[ $vars['job_id'] ])) {
+    $vars['blast_job']->form_options = $job_data[ $vars['job_id'] ];
+  }
+  if (isset($vars['recent_jobs'][ $vars['job_id'] ])) {
+    $vars['blast_job']->display = $vars['recent_jobs'][ $vars['job_id'] ];
+  }
+  
+  // Determine the blast command for display.
+  $vars['blast_job']->display['blast_cmd'] = $vars['blast_job']->form_options['program'];
+  foreach($vars['blast_job']->form_options['options'] as $key => $value) {
+      $vars['blast_job']->display['blast_cmd'] .= ' -' . $key. ' ' . $value ;
+  }
+  
+  // Load the XML file.
+  $vars['xml'] = NULL;
+  if (is_readable($vars['xml_filename'])) {
+    $vars['xml'] = simplexml_load_file($vars['xml_filename']);
+  }
+
 }
 
 /**

+ 1 - 0
theme/blast_user_menupage.tpl.php

@@ -73,6 +73,7 @@ local alignment search tool. J. Mol. Biol., 215, 403–410.</blockquote>
       'header' => array('Query Information', 'Search Target', 'Date Requested', ''),
       'rows' => array(),
       'attributes' => array('class' => array('tripal-blast', 'recent-jobs')),
+      'sticky' => FALSE
     );
   
     foreach ($recent_jobs as $job) {

+ 25 - 30
theme/css/blast_report.css

@@ -4,72 +4,67 @@
  * Handles CSS Themeing of the BLAST Results
  */
 
-#blast_report h4 {
-  margin: 0px;
-  padding: 0px;
-}
-#blast_report img {
-  float:right;
-}
-#blast_report ul {
-  margin:10px 0 10px 10px;
-  padding: 0px;
+/* -- Ensure users see lack of results. */
+p.blast-no-results {
+  color: red;
+  font-weight: bold;
+  font-style: italic;
 }
-#blast_report th {
+
+/* -- Theme the table of results */
+table#blast_report th {
   text-align: left;
 }
-#blast_report tr td {
+table#blast_report tr td {
 	vertical-align : top;
 }
-#blast_report tr.odd td {
+table#blast_report tr.odd td {
   cursor:pointer;
 	vertical-align : top;
 }
-#blast_report .arrow {
+table#blast_report .arrow {
   background:transparent url('../images/arrows.png') no-repeat scroll 0px -16px;
   width:16px;
   height:16px;
   display:block;
 }
-#blast_report div.up {
+table#blast_report div.up {
   background-position:0px 0px;
 }
-#blast_report td.number, #blast_report th.number {
+table#blast_report td.number, #blast_report th.number {
   width: 10px;
+  border-left: none;
 }
-#blast_report td.evalue, #blast_report th.evalue {
+table#blast_report td.evalue, #blast_report th.evalue {
   width: 100px;
-  border-right: none;
 }
-#blast_report td.arrow-col, #blast_report th.arrow-col {
+table#blast_report td.arrow-col, #blast_report th.arrow-col {
   width: 10px;
-  border-left: none;
+  border-right: none;
 }
 
-/**
- * Alignment
- */
-#blast_report tr.alignment-row .title{
+/* -- Alignment */
+table#blast_report tr.alignment-row .title{
   font-weight: bold;
 }
-#blast_report tr.alignment-row .hsp-title{
+table#blast_report tr.alignment-row .hsp-title{
   padding-top: 15px;
   font-weight: bold;
 }
-#blast_report tr.alignment-row{
+table#blast_report tr.alignment-row{
   width: 100%;
 }
-#blast_report .alignment {
+table#blast_report .alignment {
   width: 625px;
 }
-#blast_report .alignment-title {
+table#blast_report .alignment-title {
   font-weight: bold;
 }
-#blast_report div.alignment-row{
+table#blast_report div.alignment-row{
   padding: 10px 30px;
   font-family: monospace;
   white-space: nowrap;
 }
-#blast_report div.alignment-subrow{
+table#blast_report div.alignment-subrow{
   padding-bottom: 15px;
 }