Prechádzať zdrojové kódy

Added db storage of blast job details and cleaned up different implementations previously storing data (edit & resubmit used drupal variables and recent jobs used session) to use the new database saved details.

Lacey Sanderson 9 rokov pred
rodič
commit
0b2634c085

+ 116 - 32
api/blast_ui.api.inc

@@ -90,6 +90,61 @@ function get_blast_database_options($type) {
   return $options;
 }
 
+/**
+ * Retrieve all the information for a blast job in a standardized node-like format.
+ *
+ * @param $job_id
+ *   The non-encoded tripal job_id.
+ * @retun
+ *   An object describing the blast job.
+ */
+function get_BLAST_job($job_id) {
+
+  $blastjob = db_query('SELECT * FROM blastjob WHERE job_id=:id', array(':id' => $job_id))->fetchObject();
+  $tripal_job = tripal_get_job($job_id);
+  
+  $job = new stdClass();
+  $job->job_id = $job_id;
+  $job->program = $blastjob->blast_program;
+  $job->options = unserialize($blastjob->options);
+  $job->date_submitted = $tripal_job->submit_date;
+  $job->date_started = $tripal_job->start_time;
+  $job->date_completed = $tripal_job->end_time;
+  
+  // TARGET BLAST DATABASE.
+  // If a provided blast database was used then load details.
+  if ($blastjob->target_blastdb ) {
+    $job->blastdb = get_blast_database(array('nid' => $blastjob->target_blastdb));
+  }
+  // Otherwise the user uploaded their own database so provide what information we can.
+  else {
+    $job->blastdb = new stdClass();
+    $job->blastdb->db_name = 'User Uploaded';
+    $job->blastdb->db_path = $blastjob->target_file;
+    $job->blastdb->linkout = new stdClass();
+    $job->blastdb->linkout->none = TRUE;
+    
+    if ($job->program == 'blastp' OR $job->program == 'tblastn') {
+      $job->blastdb->db_dbtype = 'protein';
+    }
+    else {
+      $job->blastdb->db_dbtype = 'nucleotide';
+    }
+  }
+  
+  // FILES.
+  $job->files = new stdClass();
+  $job->files->query = $blastjob->query_file;
+  $job->files->target = $blastjob->target_file;
+  $job->files->result = new stdClass();
+  $job->files->result->archive = $blastjob->result_filestub . '.asn';
+  $job->files->result->xml = $blastjob->result_filestub . '.xml';
+  $job->files->result->tsv = $blastjob->result_filestub . '.tsv';
+  $job->files->result->html = $blastjob->result_filestub . '.html';
+  
+  return $job;
+}
+
 /**
  * Run BLAST (should be called from the command-line)
  *
@@ -108,12 +163,10 @@ function get_blast_database_options($type) {
  */
 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';
-  $output_file_xml = $output_dir . DIRECTORY_SEPARATOR . $output_filestub . '.blast.xml';
-  $output_file_tsv = $output_dir . DIRECTORY_SEPARATOR . $output_filestub . '.blast.tsv';
-  $output_file_html = $output_dir . DIRECTORY_SEPARATOR . $output_filestub . '.blast.html';
+  $output_file = $output_filestub . '.asn';
+  $output_file_xml = $output_filestub . '.xml';
+  $output_file_tsv = $output_filestub . '.tsv';
+  $output_file_html = $output_filestub . '.html';
 
   print "\nExecuting $program\n\n";
   print "Query: $query\n";
@@ -287,7 +340,8 @@ function get_blastdb_linkout_regex($node, $options = array()) {
 /**
  * Return a list of recent blast jobs to be displayed to the user.
  *
- * NOTE: The calling function will be expected to do the rendering.
+ * @param $programs
+ *   An array of blast programs you want jobs to be displayed for (ie: blastn, blastx, tblastn, blastp)
  *
  * @return
  *   An array of recent jobs.
@@ -297,43 +351,30 @@ function get_recent_blast_jobs($programs = array()) {
   $filter_jobs = !empty($programs);
   
   // Retrieve any recent jobs from the session variable.
-  $sid = session_id();  
-  if (isset($_SESSION['all_jobs'][$sid])) {
+  if (isset($_SESSION['blast_jobs'])) {
 
     $jobs = array();
-    foreach ($_SESSION['all_jobs'][$sid] as $job_id => $job) {
+    foreach ($_SESSION['blast_jobs'] as $job_secret) {
       $add = TRUE;
       
+      $job_id = blast_ui_reveal_secret($job_secret);
+      $job = get_BLAST_job($job_id);
+      
       // @TODO: Check that the results are still available.
       // This is meant to replace the arbitrary only show jobs executed less than 48 hrs ago.
-      
+
       // Remove jobs from the list that are not of the correct program.
-      if ($filter_jobs AND !in_array($job['program'], $programs)) {
+      if ($filter_jobs AND !in_array($job->program, $programs)) {
         $add = FALSE;
       }
-      
+
       if ($add) {
 
-        // Format the query information for display.
-        // Easiest case: if there is only one query header then show it.
-        if (sizeof($job['query_defs']) == 1 AND isset($job['query_defs'][0])) {
-          $job['query_info'] = $job['query_defs'][0];
-        }
-        // If we have at least one header then show that along with the count of queries.
-        elseif (isset($job['query_defs'][0])) {
-          $job['query_info'] = sizeof($job['query_defs']) . ' queries including "' . $job['query_defs'][0] . '"';
-        }
-        // If they provided a sequence with no header.
-        elseif (empty($job['query_defs'])) {
-          $job['query_info'] = 'Unnamed Query';
-        }
-        // At the very least show the count of queries.
-        else {
-          $job['query_info'] = sizeof($job['query_defs']) . ' queries';
-        }
-      
-        $jobs[$job_id] = $job;
+        $job->query_summary = format_query_headers($job->files->query);
+
+        $jobs[] = $job;
       }
+
     }
       
     return $jobs;
@@ -343,6 +384,49 @@ function get_recent_blast_jobs($programs = array()) {
   }
 }
 
+/**
+ * Retrieve the number of recent jobs.
+ */
+function get_number_of_recent_jobs() {
+  if (isset($_SESSION['blast_jobs'])) {
+    return sizeof($_SESSION['blast_jobs']);
+  } 
+  return 0;
+}
+
+/** 
+ * Summarize a fasta file based on it's headers.
+ *
+ * @param $file
+ *   The full path to the FASTA file.
+ *
+ * @return
+ *   A string describing the number of sequences and often including the first query header.
+ */
+function format_query_headers($file) {
+
+  $headers = array();
+  exec('grep ">" '.$file, $headers);
+
+  // Easiest case: if there is only one query header then show it.
+  if (sizeof($headers) == 1 AND isset($headers[0])) {
+    return ltrim($headers[0], '>');
+  }
+  // If we have at least one header then show that along with the count of queries.
+  elseif (isset($headers[0])) {
+    return sizeof($headers) . ' queries including "' . ltrim($headers[0], '>') . '"';
+  }
+  // If they provided a sequence with no header.
+  elseif (empty($headers)) {
+    return 'Unnamed Query';
+  }
+  // At the very least show the count of queries.
+  else {
+    return sizeof($headers) . ' queries';
+  }
+
+}
+
 /**
  * Generate an image of HSPs for a given hit.
  *          

+ 113 - 1
blast_ui.install

@@ -26,6 +26,7 @@ function blast_ui_install() {
  */
 function blast_ui_schema(){
 
+  // A table ot keep extra information related to blastdb nodes.
   $schema['blastdb'] = array(
     'description' => t('The base table for blastdb node'),
     'fields' => array(
@@ -79,7 +80,58 @@ function blast_ui_schema(){
        'nid' => array('nid'),
     ),
   );
-
+  
+  // BLAST JOBS
+  // ------------------------
+  // Keeps track of additional information related to tripal blast jobs.
+  $schema['blastjob'] = array(
+    'description' => t('Keeps track of additional information related to tripal blast jobs.'),
+    'fields' => array(
+      'job_id' => array(
+        'description' => t('The Tripal job_id for the blast job.'),
+        'type' => 'int',
+        'unsigned' => true,
+        'not null' => true,
+      ),
+      'blast_program' => array(
+        'description' => t('The program to use to run the blast (ie: blastn, blastp, etc.).'),
+        'type' => 'varchar',
+        'length' => 20,
+        'not null' => true,
+      ),
+      'target_blastdb' => array(
+        'description' => t('The nid of the blastdb used to search against; NULL if target was uploaded.'),
+        'type' => 'int',
+        'unsigned' => true,
+      ),
+      'target_file' => array(
+        'description' => t('The absolute path to the uploaded blast database after it was run through makeblastdb; NULL if target was NOT uploaded.'),
+        'type' => 'text',
+      ),
+      'query_file' => array(
+        'description' => t('The absolute path to the query file.'),
+        'type' => 'text',
+      ),
+      'result_filestub' => array(
+        'description' => t('The absolute path and filename (without extension) of the blast results.'),
+        'type' => 'text',
+      ),
+      'options' => array(
+        'description' => t('A serialized array of options selected for the blast job where the key is the machine name of the option used when calling blast (ie: gapextend) and the value is the value of the option.'),
+        'type' => 'text',
+      ),
+    ),
+    'primary key' => array('job_id'),
+    'foreign keys' => array(
+      'job_id' => array(
+        'table' => 'tripal_jobs',
+        'columns' => array(
+          'job_id' => 'job_id',
+        ),
+      ),
+    ),
+  );
+  
   return $schema;
 }
 
@@ -136,3 +188,63 @@ function blast_ui_update_7102() {
   );
 
 }
+
+/**
+ * Add saving of blast job information for recent job list & resubmit functionality.
+ */
+function blast_ui_update_7103() {
+  $schema = array();
+
+  // Keeps track of additional information related to tripal blast jobs.
+  $schema['blastjob'] = array(
+    'description' => t('Keeps track of additional information related to tripal blast jobs.'),
+    'fields' => array(
+      'job_id' => array(
+        'description' => t('The Tripal job_id for the blast job.'),
+        'type' => 'int',
+        'unsigned' => true,
+        'not null' => true,
+      ),
+      'blast_program' => array(
+        'description' => t('The program to use to run the blast (ie: blastn, blastp, etc.).'),
+        'type' => 'varchar',
+        'length' => 20,
+        'not null' => true,
+      ),
+      'target_blastdb' => array(
+        'description' => t('The nid of the blastdb used to search against; NULL if target was uploaded.'),
+        'type' => 'int',
+        'unsigned' => true,
+      ),
+      'target_file' => array(
+        'description' => t('The absolute path to the uploaded blast database after it was run through makeblastdb; NULL if target was NOT uploaded.'),
+        'type' => 'text',
+      ),
+      'query_file' => array(
+        'description' => t('The absolute path to the query file.'),
+        'type' => 'text',
+      ),
+      'result_filestub' => array(
+        'description' => t('The absolute path and filename (without extension) of the blast results.'),
+        'type' => 'text',
+      ),
+      'options' => array(
+        'description' => t('A serialized array of options selected for the blast job where the key is the machine name of the option used when calling blast (ie: gapextend) and the value is the value of the option.'),
+        'type' => 'text',
+      ),
+    ),
+    'primary key' => array('job_id'),
+    'foreign keys' => array(
+      'job_id' => array(
+        'table' => 'tripal_jobs',
+        'columns' => array(
+          'job_id' => 'job_id',
+        ),
+      ),
+    ),
+  );
+  
+  // First create the tables.
+  db_create_table('blastjob', $schema['blastjob']);
+  
+}

+ 8 - 1
blast_ui.module

@@ -168,7 +168,14 @@ function blast_ui_theme() {
     'variables' => array('hsps' => NULL),
     'path' => "$path/theme",
   );
-
+  
+  // Lists the recent blast jobs for a given user/session.
+  $items['blast_recent_jobs'] = array(
+    'template' => 'blast_recent_jobs',
+    'variables' => array('programs' => NULL),
+    'path' => "$path/theme",
+  );
+  
   // Module Help
   $items['blast_help'] = array(
     'template' => 'blast_help',

+ 72 - 51
includes/blast_ui.form_advanced_options.inc

@@ -23,17 +23,17 @@
  *   The current state fo the form passed in as $form.
  */
 function blast_ui_blastn_advanced_options_form(&$form, $form_state) {
-  $all_job_data = variable_get('job_data', '');
-  if (isset($_GET['jid']) && isset($all_job_data)) {    
-     $jid = blast_ui_reveal_secret($_GET['jid']);
-     $job_data = $all_job_data[$jid];
+  
+  // Edit and Resubmit functionality.
+  // We want to pull up the details from a previous blast and fill them in as defaults
+  // for this blast.
+  if (isset($form_state['prev_blast'])) {
+    $defaults = _get_default_values($form_state['prev_blast']->options, 'blastn');
   }
   else {
-    $job_data = array();
-    $jid = 0;
+    $defaults = _get_default_values(array(), 'blastn');
   }
-  $defaults = _get_default_values($job_data, 'blastn');
-
+  
   // General parameters
   //.........................
 
@@ -171,16 +171,16 @@ function blast_ui_blastn_advanced_options_form_submit($form, $form_state) {
  *   The current state fo the form passed in as $form.
  */
 function blast_ui_blastx_advanced_options_form(&$form, $form_state) {
-  $all_job_data = variable_get('job_data', '');
-  if (isset($_GET['jid']) && isset($all_job_data)) {    
-     $jid = blast_ui_reveal_secret($_GET['jid']);
-     $job_data = $all_job_data[$jid];
+
+  // Edit and Resubmit functionality.
+  // We want to pull up the details from a previous blast and fill them in as defaults
+  // for this blast.
+  if (isset($form_state['prev_blast'])) {
+    $defaults = _get_default_values($form_state['prev_blast']->options, 'blastn');
   }
   else {
-    $job_data = array();
-    $jid = 0;
+    $defaults = _get_default_values(array(), 'blastx');
   }
-  $defaults = _get_default_values($job_data, 'blastx');
 
    $form['ALG']['GParam'] = array(
    '#type' => 'fieldset',
@@ -306,16 +306,16 @@ function blast_ui_blastx_advanced_options_form_submit($form, $form_state) {
  *   The current state fo the form passed in as $form.
  */
 function blast_ui_blastp_advanced_options_form(&$form, $form_state) {
-  $all_job_data = variable_get('job_data', '');
-  if (isset($_GET['jid']) && isset($all_job_data)) {    
-     $jid = blast_ui_reveal_secret($_GET['jid']);
-     $job_data = $all_job_data[$jid];
+
+  // Edit and Resubmit functionality.
+  // We want to pull up the details from a previous blast and fill them in as defaults
+  // for this blast.
+  if (isset($form_state['prev_blast'])) {
+    $defaults = _get_default_values($form_state['prev_blast']->options, 'blastn');
   }
   else {
-    $job_data = array();
-    $jid = 0;
+    $defaults = _get_default_values(array(), 'blastp');
   }
-  $defaults = _get_default_values($job_data, 'blastp');
 
   //General parameters
 
@@ -968,16 +968,16 @@ function ajax_dependent_dropdown_callback($form, $form_state) {
  *   The current state fo the form passed in as $form.
  */
 function blast_ui_tblastn_advanced_options_form(&$form, $form_state) {
-  $all_job_data = variable_get('job_data', '');
-  if (isset($_GET['jid']) && isset($all_job_data)) {    
-     $jid = blast_ui_reveal_secret($_GET['jid']);
-     $job_data = $all_job_data[$jid];
+
+  // Edit and Resubmit functionality.
+  // We want to pull up the details from a previous blast and fill them in as defaults
+  // for this blast.
+  if (isset($form_state['prev_blast'])) {
+    $defaults = _get_default_values($form_state['prev_blast']->options, 'blastn');
   }
   else {
-    $job_data = array();
-    $jid = 0;
+    $defaults = _get_default_values(array(), 'tblastn');
   }
-  $defaults = _get_default_values($job_data, 'tblastn');
 
   $form['ALG']['GParam'] = array(
    '#type' => 'fieldset',
@@ -1078,28 +1078,28 @@ function blast_ui_tblastn_advanced_options_form_submit($form, $form_state) {
 
 }
 
-/*
+/**
  * Get default form values; may come from saved job data if user is re-running
  *   a previous job.
  */
-function _get_default_values($job_data) {
+function _get_default_values($options) {
   // restore previous values or set to default
-  $max_target = (isset($job_data['options']['max_target_seqs'])) 
-  					? $job_data['options']['max_target_seqs'] : 10;
-  $short_queries = (isset($job_data['options']['shortQueries'])) 
-  					? $job_data['options']['shortQueries'] : true;
-  $evalue = (isset($job_data['options']['evalue'])) 
-  					? $job_data['options']['evalue'] : .001;
-  $word_size = (isset($job_data['options']['word_size'])) 
-  					? $job_data['options']['word_size'] : 11;
-  $qRange = (isset($job_data['options']['culling_limit'])) 
-  					? $job_data['options']['culling_limit'] : 0;
+  $max_target = (isset($options['max_target_seqs'])) 
+  					? $options['max_target_seqs'] : 10;
+  $short_queries = (isset($options['shortQueries'])) 
+  					? $options['shortQueries'] : true;
+  $evalue = (isset($options['evalue'])) 
+  					? $options['evalue'] : .001;
+  $word_size = (isset($options['word_size'])) 
+  					? $options['word_size'] : 11;
+  $qRange = (isset($options['culling_limit'])) 
+  					? $options['culling_limit'] : 0;
 
   $matchmiss = 0;
-  $reward = (isset($job_data['options']['reward'])) 
-  					? $job_data['options']['reward'] : 1;
-  $penalty = (isset($job_data['options']['penalty'])) 
-  					? $job_data['options']['penalty'] : -2;
+  $reward = (isset($options['reward'])) 
+  					? $options['reward'] : 1;
+  $penalty = (isset($options['penalty'])) 
+  					? $options['penalty'] : -2;
   if ($reward == 1) {
   	switch ($penalty) {
   		case -1: $matchmiss = 5; break;
@@ -1119,10 +1119,10 @@ function _get_default_values($job_data) {
   }
   
   $gap = 0;
-  $gapopen = (isset($job_data['options']['gapopen'])) 
-  					? $job_data['options']['gapopen'] : 5;
-  $gapextend = (isset($job_data['options']['gapextend'])) 
-  					? $job_data['options']['gapextend'] : 2;
+  $gapopen = (isset($options['gapopen'])) 
+  					? $options['gapopen'] : 5;
+  $gapextend = (isset($options['gapextend'])) 
+  					? $options['gapextend'] : 2;
   if ($gapextend == 2) {
   	switch ($gapopen) {
   		case 5: $gap = 0; break;
@@ -1142,8 +1142,8 @@ function _get_default_values($job_data) {
 // eksc- need to implement query range limit
 //  $q_range = 0;
   
-  $matrix = (isset($job_data['options']['matrix'])) 
-  					? $job_data['options']['matrix'] : 'PAM30';
+  $matrix = (isset($options['matrix'])) 
+  					? $options['matrix'] : 'PAM30';
   return array(
   	'max_target_seqs' => $max_target,
   	'short_queries'   => $short_queries,
@@ -1156,6 +1156,12 @@ function _get_default_values($job_data) {
   );
 }//_get_default_values
 
+/**
+ * Get a list of options for the max_target_seq blast option.
+ *
+ * The options are the same for all programs
+ * and describe the maximum number of aligned sequences to keep.
+ */
 function _get_max_target($which) {
 	switch ($which) {
 	  case 'blastn':
@@ -1176,6 +1182,9 @@ function _get_max_target($which) {
 	}//switch
 }
 
+/**
+ * Get a list of options for work size.
+ */
 function _get_word_size($which) {
 	switch ($which) {
 		case 'blastn':
@@ -1204,6 +1213,9 @@ function _get_word_size($which) {
 	}//switch
 }
 
+/**
+ * Get a list of options for match/mismatch ratio.
+ */
 function _get_match_mismatch($which) {
 	switch ($which) {
 		case 'blastn':
@@ -1218,6 +1230,9 @@ function _get_match_mismatch($which) {
   }//switch
 }
 
+/**
+ * Get a list of options for gaps.
+ */
 function _get_gap($which) {
 	switch ($which) {
 		case 'blastn':
@@ -1233,6 +1248,9 @@ function _get_gap($which) {
    }//switch
 }
 
+/**
+ * Translate above gap options into blast gap open and extend costs.
+ */
 function _set_gap($gap_key) {
  switch ($gap_key) {
    case 0:
@@ -1268,6 +1286,9 @@ function _set_gap($gap_key) {
   return array('gapOpen' => $gapOpen, 'gapExtend' => $gapExtend);
 }
 
+/**
+ * Translate mismatch/match ratio option into blast penalty/reward options.
+ */
 function _set_match_mismatch($m_m) {
   switch ($m_m) {
    case 0:

+ 141 - 125
includes/blast_ui.form_per_program.inc

@@ -15,7 +15,7 @@
  */
 function blast_ui_per_blast_program_form($form, $form_state) {
 
-  //  CSS support to the form
+  // CSS support to the form
   $form['#attached']['css'] = array(
     drupal_get_path('module', 'blast_ui') . '/theme/css/form.css',
   );
@@ -23,16 +23,44 @@ function blast_ui_per_blast_program_form($form, $form_state) {
   // We are going to lay out this form as two choices: either look at a recent blast
   // or execute a new one. We want to theme accordingly so set a class to aid us in such.
   $form['#attributes'] = array('class' => array('blast-choice-form'));
-  
-  // @deepaksomanadh - Code added for edit and resubmit funcitonality
-  //   Approach: persist the form data and read it back using JobID
-  $job_data = variable_get('job_data', '');
-  if (isset($_GET['jid']) && isset($job_data)) {    
-    $jid = blast_ui_reveal_secret($_GET['jid']);
-  }  
-  else {
-    $job_data = array();
-    $jid = 0;
+
+  // Determine some defaults.
+  $defaults = array(
+    'FASTA' => NULL,
+    'SELECT_DB' => NULL,
+  );
+    
+  // Edit and Resubmit functionality.
+  // We want to pull up the details from a previous blast and fill them in as defaults
+  // for this blast.
+  // @todo: handle file uploads better; currently for the query we put the file contents
+  // in the text area causing reupload and we simply do not support re-using of an uploaded target.
+  if (isset($_GET['resubmit'])) {    
+    $prev_blast = get_BLAST_job(blast_ui_reveal_secret($_GET['resubmit']));
+    
+    // First of all warn if the uploaded their search target last time 
+    // since we don't support that now.
+    if (!isset($prev_blast->blastdb->nid)) {
+      drupal_set_message('You will need to re-upload your <em>Search Target</em> database.','warning');
+    }
+    // Andi f they didn't upload a target then set a default for the select list.
+    else {
+      $defaults['SELECT_DB'] = $prev_blast->blastdb->nid;
+    }
+    
+    // Finally set a default for the query. Since we don't support defaults for file uploads,
+    // we need to get the contents of the file and put them in our textarea.
+    if (is_readable($prev_blast->files->query)) {
+      $defaults['FASTA'] = file_get_contents($prev_blast->files->query);
+    }
+    // There should always be a query file (both if uploaded or not) so if we cant find it
+    // then it must have been cleaned up :-( -- warn the user.
+    else {
+      drupal_set_message('Unable to retrieve previous query sequence; please re-upload it.', 'error');
+    }
+    
+    // Finally save the previous blast details for use by the advanced option forms.
+    $form_state['prev_blast'] = $prev_blast;
   }
 
   // Determine the BLAST program.
@@ -80,12 +108,9 @@ function blast_ui_per_blast_program_form($form, $form_state) {
   );
 
   // CHOOSE RECENT BLAST RESULTS
-  //-----------------------------------
-  // Gets the list of recent jobs filtered to the current blast program (ie: blastn).
-  $recent_jobs = get_recent_blast_jobs(array($blast_program));
-  
+  //-----------------------------------  
   // If there are recent jobs then show a table of them.
-  if ($recent_jobs) {
+  if (get_number_of_recent_jobs()) {
 
     $form['A'] = array(
       '#type' => 'fieldset',
@@ -94,28 +119,10 @@ function blast_ui_per_blast_program_form($form, $form_state) {
       '#collapsible' => TRUE,
       '#collapsed' => TRUE
     );
-    
-    $table = array(
-      '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) {
-
-      // Define a row for the current job.
-      $table['rows'][] = array(
-        $job['query_info'],
-        $job['target'],
-        $job['date'],
-        l('See Results', $job['job_output_url'])
-      );
-    }
 
     $form['A']['job_table'] = array(
       '#type' => 'markup',
-      '#markup' => theme('table', $table),
+      '#markup' => theme('blast_recent_jobs', array($blast_program)),
     );
   }
 
@@ -165,7 +172,7 @@ function blast_ui_per_blast_program_form($form, $form_state) {
     '#type' => 'textarea',
     '#title' => t('Enter FASTA sequence(s)'),
     '#description'=>t('Enter query sequence(s) in the text area.'),
-    '#default_value' => isset($job_data[$jid]['fasta']) ? $job_data[$jid]['fasta'] : '',
+    '#default_value' => $defaults['FASTA'],
     '#prefix' => '<div id="fasta-textarea">',
     '#suffix' => '</div>',
   );
@@ -213,7 +220,7 @@ function blast_ui_per_blast_program_form($form, $form_state) {
     '#type' => 'select',
     '#title' => t('%type BLAST Databases:', array('%type' => ucfirst($db_type))),
     '#options' => $options,
-    '#default_value' => isset($job_data[$jid]['db_option']) ? $job_data[$jid]['db_option'] : 0,
+    '#default_value' => $defaults['SELECT_DB'],
   );
 
   if (variable_get('blast_ui_allow_target_upload', FALSE)) {
@@ -383,19 +390,38 @@ function blast_ui_per_blast_program_form_submit($form, &$form_state) {
     $mdb_type = 'prot';
   }
 
-  // If the query was submitted via the texrfield then create a file containing it
+  // We want to save information about the blast job to the database for recent jobs &
+  // edit and resubmit functionality.
+  // First set defaults.
+  $blastjob = array(
+    'job_id' => NULL, 
+    'blast_program' => $form_state['values']['blast_program'],
+    'target_blastdb' => (isset($form_state['values']['SELECT_DB'])) ? $form_state['values']['SELECT_DB'] : NULL,
+    'target_file' => NULL,
+    'query_file' => NULL,
+    'result_filestub' => NULL,
+    'options' => serialize(array())
+  );
+  
+  // QUERY
+  //-------------------------
+  // BLAST can only take the query as a file;
+  // therefore, if it was submitted via the textfield we need to create a file containing
+  // the submitted sequence.
   if (isset($form_state['qFlag'])) {
     if ($form_state['qFlag'] == 'seqQuery') {
       $seq_content = $form_state['values']['FASTA'];
-      $query = '/tmp/' . date('YMd_His') . '_query.fasta';
-      file_put_contents ($query , $seq_content);
+      $blastjob['query_file'] = '/tmp/' . date('YMd_His') . '_query.fasta';
+      file_put_contents ($blastjob['query_file'], $seq_content);
     }
     elseif ($form_state['qFlag'] == 'upQuery') {
-      $query = $form_state['upQuery_path'];
+      $blastjob['query_file'] = $form_state['upQuery_path'];
     }
   }
 
-  // If the BLAST database was uploaded then use it to run the BLAST
+  // TARGET
+  //-------------------------
+  // If the BLAST database was uploaded then we need to format it to make it compatible with blast.
   if ($form_state['dbFlag'] == 'upDB') {
 
     // Since we only support using the -db flag (not -subject) we need to create a
@@ -418,8 +444,8 @@ your sequence headers include pipes (i.e.: | ) they adhere to '
 
       $error = TRUE;
     }
-  }//upload target db
-  
+    
+  }
   // Otherwise, we are using one of the website provided BLAST databases so form the
   // BLAST command accordingly
   elseif ($form_state['dbFlag'] == 'blastdb') {
@@ -428,21 +454,10 @@ your sequence headers include pipes (i.e.: | ) they adhere to '
     $blastdb_name = $blastdb_node->db_name;
     $blastdb_with_path = $blastdb_node->db_path;
   }
+  
+  $blastjob['target_file'] = $blastdb_with_path;
 
-  // Now let each program process its own advanced options.
-  $advanced_options = array();
-  $advanced_options_form_submit = 'blast_ui_' . $blast_program . '_advanced_options_form_submit';
-  if (function_exists($advanced_options_form_submit)) {
-    $advanced_options = call_user_func_array(
-      $advanced_options_form_submit,
-      array($form['B'], $form_state)
-    );
-  }
-  else {
-  	$advanced_options = array('none' => 0);
-  }
-
-  // Set path to a BLAST target file to check for its existence
+  // Determine the path to the blast database with extension.
   if ($mdb_type == 'nucl' && (preg_match('/\.[pn]al/', $blastdb_with_path) == 0)) {  
     // Suffix may be .nsq or .nal
     if (is_readable("$blastdb_with_path.nsq")) {
@@ -463,98 +478,99 @@ your sequence headers include pipes (i.e.: | ) they adhere to '
   }
   else {
     $blastdb_with_suffix = $blastdb_with_path;
-  }    
+  }
+  
+  if (!is_readable($blastdb_with_suffix)) {
+    $error = TRUE;
+    
+    $dbfile_uploaded_msg = ($form_state['dbFlag'] == 'upDB') 
+        ? 'The BLAST database was submitted via user upload.' 
+        : 'Existing BLAST Database was chosen.';
+    tripal_report_error(
+      'blast_ui',
+      TRIPAL_ERROR,
+      "BLAST database %db unaccessible. %msg",
+      array('%db' => $blastdb_with_path, '%msg' => $dbfile_uploaded_msg)
+    );
+    $msg = "$dbfile_uploaded_msg BLAST database '$blastdb_with_path' is unaccessible. ";
+    $msg .= "Please contact the site administrator.";
+    drupal_set_message($msg, 'error');
+  }
+  
+  // ADVANCED OPTIONS
+  //-------------------------
+  // Now let each program process its own advanced options.
+  $advanced_options = array();
+  $advanced_options_form_submit = 'blast_ui_' . $blast_program . '_advanced_options_form_submit';
+  if (function_exists($advanced_options_form_submit)) {
+    $advanced_options = call_user_func_array(
+      $advanced_options_form_submit,
+      array($form['B'], $form_state)
+    );
+  }
+  else {
+  	$advanced_options = array('none' => 0);
+  }
+  
+  $blastjob['options'] = serialize($advanced_options);
 
+  // SUBMIT JOB TO TRIPAL
+  //-------------------------
   // Actually submit the BLAST Tripal Job
-  if (is_readable($blastdb_with_suffix)) {
+  if (!$error) {
     // BLAST target exists.
     global $user;
 
-    $output_filestub = date('YMd_His');
+    // We want to save all result files (.asn, .xml, .tsv, .html) in the public files directory.
+    // Usually [drupal root]/sites/default/files.
+    $output_dir = variable_get('file_public_path', conf_path() . '/files') 
+      . DIRECTORY_SEPARATOR . 'tripal' . DIRECTORY_SEPARATOR . 'tripal_blast';
+    $output_filestub = $output_dir . DIRECTORY_SEPARATOR . date('YMd_His') . '.blast';
+    
     $job_args = array(
       'program' => $blast_program,
-      'query' => $query,
+      'query' => $blastjob['query_file'],
       'database' => $blastdb_with_path,
       'output_filename' => $output_filestub,
       'options' => $advanced_options
     );
-    
+
     $job_id = tripal_add_job(
-      t('BLAST (@program): @query', array('@program' => $blast_program, '@query' => $query)),
+      t('BLAST (@program): @query', array('@program' => $blast_program, '@query' => $blastjob['query_file'])),
       'blast_job',
       'run_BLAST_tripal_job',
       $job_args,
       $user->uid
     );
     
-    $job_data = variable_get('job_data', '');
-    $seq_rows = explode(PHP_EOL, $seq_content);
-    foreach($seq_rows as $row) {
-      if (strpos($row, ">") !== FALSE) {
-       $query_def[] = trim($row, "> \t\n\r\0\x0B");
-      }
-    }
-  
-    $job_data[$job_id] = 
-      array(
-        'program'   => $blast_program,
-        'job_url'   => current_path(),
-        'fasta'     => $seq_content,
-        'query_def' => $query_def,
-        'db_name'   => $blastdb_node->db_name,
-        'db_option' => $selected_db,
-        'options'   => $advanced_options,
-      );
-    
-    variable_set('job_data', $job_data);
-    //@deepaksomanadh create session and save the recent jobs in respective session
-    if (session_status() === PHP_SESSION_NONE) {
-       session_start();
-    }
-    $sid = session_id();
-    $job_encode_id = blast_ui_make_secret($job_id);
-    $job_url = "blast/report/$job_encode_id";
+    $blastjob['result_filestub'] = $output_filestub;
+    $blastjob['job_id'] = $job_id;
+
+    // SAVE JOB INFO
+    //-------------------------
+    drupal_write_record('blastjob', $blastjob);
 
-    $all_jobs = $_SESSION['all_jobs'];
-    
-    $session_jobs = $all_jobs[$sid];
-    $session_jobs[$job_id] = 
-      array(
-        'job_output_url'=> $job_url, 
-        'query_defs'    => $query_def,
-        'target'        => $blastdb_name,
-        'program'       => $blast_program,
-        'date'          => date('Y-M-d h:i:s'),
-       );
-    $all_jobs[$sid] = $session_jobs;
-    $_SESSION['all_jobs'] = $all_jobs;
-  
-// Comment out this line to run BLAST by hand via the command:
-//   drush trp-run-jobs --username=admin 
-    tripal_jobs_launch(1, $job_id);
-    
     //Encode the job_id
     $job_encode_id = blast_ui_make_secret($job_id);
     
+    // RECENT JOBS
+    //-------------------------
+    if (!isset($_SESSION['blast_jobs'])) {
+      $_SESSION['blast_jobs'] = array();
+    }
+    $_SESSION['blast_jobs'][] = $job_encode_id;
+
+    // NOTE: Originally there was a call to tripal_launch_jobs() here. That should
+    // NEVER be done since it runs possibly long jobs in the page load causing time-out
+    // issues. If you do not want to run tripal jobs manually, look into installing
+    // Tripal daemon which will run jobs as they're submitted or set up a cron job to
+    // launch the tripal jobs on a specified schedule.
+    
     // Redirect to the BLAST results page
     drupal_goto("blast/report/$job_encode_id");
-  }//BLAST target is readable
-  
-  // BLAST target is unreadable
-  else {
-    $dbfile_uploaded_msg = ($form_state['dbFlag'] == 'upDB') 
-        ? 'The BLAST database was submitted via user upload.' 
-        : 'Existing BLAST Database was chosen.';
-    tripal_report_error(
-      'blast_ui',
-      TRIPAL_ERROR,
-      "BLAST database %db unaccessible. %msg",
-      array('%db' => $blastdb_with_path, '%msg' => $dbfile_uploaded_msg)
-    );
-    $msg = "$dbfile_uploaded_msg BLAST database '$blastdb_with_path' is unaccessible. ";
-    $msg .= "Please contact the site administrator.";
-    drupal_set_message($msg, 'error');
   }
+
+
 }
 
 /**

+ 1 - 30
theme/blast_nucleotide_user_menupage.tpl.php

@@ -66,33 +66,4 @@ local alignment search tool. J. Mol. Biol., 215, 403–410.</blockquote>
   </tr>
 </table>
 
-<!-- Recent Jobs -->
-<?php
-
-  // Gets the list of recent jobs filtered to the current blast program (ie: blastn).
-  $recent_jobs = get_recent_blast_jobs(array('blastn','blastx'));
-  if ($recent_jobs) {
-  
-    print '<h2>Recent Jobs</h2>';
-    
-    $table = array(
-      '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) {
-
-      // Define a row for the current job.
-      $table['rows'][] = array(
-        $job['query_info'],
-        $job['target'],
-        $job['date'],
-        l('See Results', $job['job_output_url'])
-      );
-    }
-    
-    print theme('table', $table);
-  }
-?>
+<?php print theme('blast_recent_jobs', array('blastn','blastx')); ?>

+ 1 - 30
theme/blast_protein_user_menupage.tpl.php

@@ -65,33 +65,4 @@ local alignment search tool. J. Mol. Biol., 215, 403–410.</blockquote>
   </tr>
 </table>
 
-<!-- Recent Jobs -->
-<?php
-
-  // Gets the list of recent jobs filtered to the current blast program (ie: blastn).
-  $recent_jobs = get_recent_blast_jobs(array('tblastn','blastp'));
-  if ($recent_jobs) {
-  
-    print '<h2>Recent Jobs</h2>';
-    
-    $table = array(
-      '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) {
-
-      // Define a row for the current job.
-      $table['rows'][] = array(
-        $job['query_info'],
-        $job['target'],
-        $job['date'],
-        l('See Results', $job['job_output_url'])
-      );
-    }
-    
-    print theme('table', $table);
-  }
-?>
+<?php print theme('blast_recent_jobs', array('tblastn','blastp')); ?>

+ 32 - 0
theme/blast_recent_jobs.tpl.php

@@ -0,0 +1,32 @@
+<?php
+/**
+ *
+ */
+
+// Gets the list of recent jobs filtered to the current blast program (ie: blastn).
+$recent_jobs = get_recent_blast_jobs($programs);
+if ($recent_jobs) {
+
+  print '<h2>Recent Jobs</h2>';
+  
+  $table = array(
+    '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) {
+
+    // Define a row for the current job.
+    $table['rows'][] = array(
+      $job->query_summary,
+      $job->blastdb->db_name,
+      format_date($job->date_submitted, 'medium'),
+      l('See Results', 'blast/report/'.blast_ui_make_secret($job->job_id))
+    );
+  }
+  
+  print theme('table', $table);
+}
+?>

+ 18 - 52
theme/blast_report.tpl.php

@@ -1,28 +1,23 @@
 <?php
-
 /**
  * Display the results of a BLAST job execution
- *
- * Variables Available in this template:
- *   $xml_filename: The full path & filename of XML file containing the BLAST results
- *    @deepaksomanadh: $job_data = meta data related to the current job
  */
 
 // Set ourselves up to do link-out if our blast database is configured to do so.
 $linkout = FALSE;
-if ($blastdb->linkout->none === FALSE) {
-  $linkout_type  = $blastdb->linkout->type;
-  $linkout_regex = $blastdb->linkout->regex;
+if ($blast_job->blastdb->linkout->none === FALSE) {
+  $linkout_type  = $blast_job->blastdb->linkout->type;
+  $linkout_regex = $blast_job->blastdb->linkout->regex;
   
   // Note that URL prefix is not required if linkout type is 'custom'
-  if (isset($blastdb->linkout->db_id->urlprefix) && !empty($blastdb->linkout->db_id->urlprefix)) {
-    $linkout_urlprefix = $blastdb->linkout->db_id->urlprefix;
+  if (isset($blast_job->blastdb->linkout->db_id->urlprefix) && !empty($blast_job->blastdb->linkout->db_id->urlprefix)) {
+    $linkout_urlprefix = $blast_job->blastdb->linkout->db_id->urlprefix;
   }
 
   // Check that we can determine the linkout URL.
   // (ie: that the function specified to do so, exists).
-  if (function_exists($blastdb->linkout->url_function)) {
-    $url_function = $blastdb->linkout->url_function;
+  if (function_exists($blast_job->blastdb->linkout->url_function)) {
+    $url_function = $blast_job->blastdb->linkout->url_function;
     $linkout = TRUE;
   }
 }
@@ -76,20 +71,20 @@ $no_hits = TRUE;
 <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>
+    <a href="<?php print '../../' . $blast_job->files->result->html; ?>">Alignment</a>,
+    <a href="<?php print '../../' . $blast_job->files->result->tsv; ?>">Tab-Delimited</a>,
+    <a href="<?php print '../../' . $blast_job->files->result->xml; ?>">XML</a>
   </div>
 <?php endif; ?>
   <br />
   <div class="blast-query-info"><strong>Query Information</strong>: 
-    <?php print $blast_job->display['query_info'];?></div>
+    <?php print $blast_job->files->query;?></div>
   <div class="blast-target-info"><strong>Search Target</strong>: 
-    <?php print $blast_job->display['target'];?></div>
+    <?php print $blast_job->blastdb->db_name;?></div>
   <div class="blast-date-info"><strong>Submission Date</strong>: 
-    <?php print $blast_job->display['date'];?></div>
+    <?php print format_date($blast_job->date_submitted, 'medium');?></div>
   <div class="blast-cmd-info"><strong>BLAST Command executed</strong>: 
-    <?php print $blast_job->display['blast_cmd'];?></div>
+    <?php print $blast_job->blast_cmd;?></div>
 </div>
 <br />
 
@@ -259,7 +254,7 @@ and click the <em>target name </em> to get more information about the target hit
                   'score'      => $score,
                   'e-value'    => $evalue,
                   'HSPs'       => $HSPs,
-                  'Target'     => $blastdb->title,
+                  'Target'     => $blast_job->blastdb->db_name,
                 )
               );
 
@@ -327,38 +322,9 @@ else {
 
 <p><?php print l(
   'Edit this query and re-submit', 
-  $blast_job->form_options['job_url'],
-  array('query' => array('jid' => blast_ui_make_secret($job_id))));
+  $blast_form_url,
+  array('query' => array('resubmit' => blast_ui_make_secret($job_id))));
 ?></p>
 </div>
 
-<!-- Recent Jobs -->
-<?php
-
-  // Gets the list of recent jobs filtered to the current blast program (ie: blastn).
-  
-  if ($recent_jobs) {
-  
-    print '<h2>Recent Jobs</h2>';
-    
-    $table = array(
-      '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) {
-
-      // Define a row for the current job.
-      $table['rows'][] = array(
-        $job['query_info'],
-        $job['target'],
-        $job['date'],
-        l('See Results', $job['job_output_url'])
-      );
-    }
-    
-    print theme('table', $table);
-  }
-?>
+<?php print theme('blast_recent_jobs', array()); ?>

+ 24 - 30
theme/blast_ui.theme.inc

@@ -21,44 +21,38 @@ function blast_ui_preprocess_show_blast_report(&$vars) {
   drupal_add_css($path . '/theme/css/blast_report.css');
   drupal_add_js('http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js');
 
-  // Get the filename of the BLAST results
-  $job = tripal_get_job($vars['job_id']);
-  $job_args = unserialize($job->arguments);
+  // Get blast job details.
+  $vars['blast_job'] = get_BLAST_job($vars['job_id']);
   
-//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';
-  $vars['html_filename'] = variable_get('file_public_path', conf_path() . '/files') . '/tripal/tripal_blast/' . $job_args['output_filename'] . '.blast.html';
-
-  // Add the blast database node.
-  // This is needed for link-out functionality.
-  $vars['blastdb'] = get_blast_database(array('path' => $job_args['database']));
-  
-  // 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', '');
-  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']->blast_cmd = $vars['blast_job']->program;
+  foreach($vars['blast_job']->options as $key => $value) {
+      $vars['blast_job']->blast_cmd .= ' -' . $key. ' ' . $value ;
   }
   
-  // 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 ;
+  // Determine the URL of the blast form.
+  $vars['blast_form_url'] = 'blast/nucleotide/nucleotide';
+  switch($vars['blast_job']->program) {
+    case 'blastn':
+      $vars['blast_form_url'] = 'blast/nucleotide/nucleotide';
+      break;
+    case 'blastx':
+      $vars['blast_form_url'] = 'blast/nucleotide/protein';
+      break;
+    case 'tblastn':
+      $vars['blast_form_url'] = 'blast/protein/nucleotide';
+      break;
+    case 'blastp':
+      $vars['blast_form_url'] = 'blast/protein/protein';
+      break;
   }
   
   // Load the XML file.
   $vars['xml'] = NULL;
-  if (is_readable($vars['xml_filename'])) {
-    $vars['xml'] = simplexml_load_file($vars['xml_filename']);
+  $full_path_xml = DRUPAL_ROOT . DIRECTORY_SEPARATOR . $vars['blast_job']->files->result->xml;
+  if (is_readable($full_path_xml)) {
+    $vars['xml'] = simplexml_load_file($full_path_xml);
   }
-
 }
 
 /**

+ 1 - 31
theme/blast_user_menupage.tpl.php

@@ -60,34 +60,4 @@ local alignment search tool. J. Mol. Biol., 215, 403–410.</blockquote>
   </tr>
 </table>
 
-<!-- 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>';
-    
-    $table = array(
-      '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) {
-
-      // Define a row for the current job.
-      $table['rows'][] = array(
-        $job['query_info'],
-        $job['target'],
-        $job['date'],
-        l('See Results', $job['job_output_url'])
-      );
-    }
-    
-    print theme('table', $table);
-  }
-?>
-
+<?php print theme('blast_recent_jobs', array()); ?>