Browse Source

Merge pull request #2 from LegumeFederation/7.x-1.x

Merging LegumeFederation Tripal Blast modifications
Lacey-Anne Sanderson 9 years ago
parent
commit
74784e7bb6

+ 52 - 10
api/blast_ui.api.inc

@@ -107,12 +107,12 @@ 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_file_xml = variable_get('file_public_path', conf_path() . '/files') . DIRECTORY_SEPARATOR . $output_filestub . '.blast.xml';
- $output_file_tsv = variable_get('file_public_path', conf_path() . '/files') . DIRECTORY_SEPARATOR . $output_filestub . '.blast.tsv';
- $output_file_html = variable_get('file_public_path', conf_path() . '/files') . DIRECTORY_SEPARATOR . $output_filestub . '.blast.html';
-
+  $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';
 
   print "\nExecuting $program\n\n";
   print "Query: $query\n";
@@ -123,11 +123,15 @@ function run_BLAST_tripal_job($program, $query, $database, $output_filestub, $op
 
   // Allow administrators to use an absolute path for these commands.
   // Defaults to using $PATH.
-	$blast_path = variable_get('blast_path', '');
+	$blast_path    = variable_get('blast_path', '');
 	$blast_threads = variable_get('blast_threads', '');
 	
-	$program = 	$blast_path . $program;
-	$blast_formatter_command = $blast_path .  'blast_formatter';
+	// Strip the extension off the BLAST target
+	$database = preg_replace("/(.*)\.[pn]\w\w/", '$1', $database);
+	
+	// The executables:
+	$program       = $blast_path . $program;
+	$blast_formatter_command = $blast_path . 'blast_formatter';
 
   $blast_cmd = "$program -query '$query' -db '$database' -out '$output_file' -outfmt=11";
   if (!empty($options)) {
@@ -155,7 +159,9 @@ function run_BLAST_tripal_job($program, $query, $database, $output_filestub, $op
   print "\nGenerating additional download formats...\n";
 
   print "\tXML\n";
-  system("$blast_formatter_command -archive $output_file -outfmt 5 -out $output_file_xml");
+  $format_cmd = "$blast_formatter_command -archive $output_file -outfmt 5 -out $output_file_xml";
+  print "\nExecuting $format_cmd\n\n";
+  system($format_cmd);
   if(!file_exists($output_file_xml)) {
     tripal_report_error(
       'blast_ui',
@@ -274,3 +280,39 @@ function get_blastdb_linkout_regex($node, $options = array()) {
 
   return $regex;
 }
+
+
+function get_recent_jobs() {
+  $html = '';
+  
+  $sid = session_id();  
+  $jobs = $_SESSION['all_jobs'][$sid];
+
+  // Remove jobs older than 48 hours
+  foreach ($jobs as $job_id => $job) {
+    if ($diff = abs(time() - strtotime($job['date'])) > 172800) {
+      unset($jobs[$job_id]);
+    }
+  }
+  $_SESSION['all_jobs'][$sid] = $jobs;
+  
+  if (count($jobs) > 0) {
+    $html = "
+    <h3><strong> Recent Jobs </h3>
+    <dl>";
+
+    foreach (array_reverse($jobs) as $job) {
+      $q_def = !isset($job['query_defs'][0]) ? "Query" : $job['query_defs'][0];
+      $html .= "
+        <dd>
+          <a href='" . "../../" . $job['job_output_url'] ."'>
+            $q_def X " . $job['target'] . ' (' . $job['program'] . ') - ' . $job['date'] . "
+          </a>
+        </dd>";
+    }
+     $html .= "
+    </dl>";
+  }
+  
+  return $html;
+}

+ 2 - 1
blast_ui.install

@@ -69,9 +69,11 @@ function blast_ui_schema(){
         'default' => 'link'
       ),
     ),
+    
     'indexes' => array(
       'name' => array('name'),
     ),
+    
     'primary key' => array('nid'),
     'unique keys' => array(
        'nid' => array('nid'),
@@ -79,7 +81,6 @@ function blast_ui_schema(){
   );
 
   return $schema;
-
 }
 
 /**

+ 26 - 41
blast_ui.module

@@ -9,13 +9,14 @@
 require_once 'includes/blast_ui.form_common.inc';
 require_once 'includes/blast_ui.form_advanced_options.inc';
 // NOTE: The forms themeselves are included using hook_menu to ensure they
-// are only inlcuded when needed.
+// are only included when needed.
 
 // BLAST DB Node functionality
 require_once 'includes/blast_ui.node.inc';
 
 // BLAST Link-out functionality.
 require_once 'includes/blast_ui.linkouts.inc';
+include_once('includes/blast_ui.custom.inc');
 
 // Functions specific to themeing (ie: preprocess)
 require_once 'theme/blast_ui.theme.inc';
@@ -219,7 +220,7 @@ function show_blast_output($job_id) {
   // BLAST is in the queue, running or complete in order to determine what to show the user
   //decode the job_id
   $job_id = base64_decode($job_id);
-	$job = tripal_get_job($job_id);
+  $job = tripal_get_job($job_id);
 
   // 1) Job is in the Queue
   if ($job->start_time === NULL AND $job->end_time == NULL) {
@@ -252,50 +253,15 @@ function show_blast_output($job_id) {
  *
  */
 function ajax_blast_ui_example_sequence_callback($form, $form_state) {
-
-  // First, set a default example sequence in case administrators have not yet
-  // bothered to set their own.
   $sequence_type = $form_state['values']['query_type'];
   if ($sequence_type == 'nucleotide') {
-    $default_example_sequence = '>partial lipoxygenase Glyma15g03040
-TTTCGTATGA GATTAAAATG TGTGAAATTT TGTTTGATAG GACATGGGAA
-AGGAAAAGTT GGAAAGGCTA CAAATTTAAG AGGACAAGTG TCGTTACCAA
-CCTTGGGAGC TGGCGAAGAT GCATACGATG TTCATTTTGA ATGGGACAGT
-GACTTCGGAA TTCCCGGTGC ATTTTACATT AAGAACTTCA TGCAAGTTGA
-GTTCTATCTC AAGTCTCTAA CTCTCGAAGA CATTCCAAAC CACGGAACCA
-TTCACTTCGT ATGCAACTCC TGGGTTTACA ACTCAAAATC CTACCATTCT
-GATCGCATTT TCTTTGCCAA CAATGTAAGC TACTTAAATA CTGTTATACA
-TTGTCTAACA TCTTGTTAGA GTCTTGCATG ATGTGTACCG TTTATTGTTG
-TTGTTGAACT TTACCACATG GCATGGATGC AAAAGTTGTT ATACACATAA
-ATTATAATGC AGACATATCT TCCAAGCGAG ACACCGGCTC CACTTGTCAA
-GTACAGAGAA GAAGAATTGA AGAATGTAAG AGGGGATGGA ACTGGTGAGC
-GCAAGGAATG GGATAGGATC TATGATTATG ATGTCTACAA TGACTTGGGC
-GATCCAGATA AGGGTGAAAA GTATGCACGC CCCGTTCTTG GAGGTTCTGC
-CTTACCTTAC CCTCGCAGAG GAAGAACCGG AAGAGGAAAA ACTAGAAAAG
-GTTTCTCACT AGTCACTAAT TTATTACTTT TTAATGTTTG TTTTTAGGCA
-TCTTTTCTGA TGAAATGTAT ACTTTTGATG TTTTTTTGTT TTAGCATAAC
-TGAATTAGTA AAGTGTGTTG TGTTCCTTAG AAGTTAGAAA AGTACTAAGT
-ATAAGGTCTT TGAGTTGTCG TCTTTATCTT AACAGATCCC AACAGTGAGA
-AGCCCAGTGA TTTTGTTTAC CTTCCGAGAG ATGAAGCATT TGGTCACTTG
-AAGTCATCAG ATTTTCTCGT TTATGGAATC AAATCAGTGG CTCAAGACGT
-CTTGCCCGTG TTGACTGATG CGTTTGATGG CAATCTTTTG AGCCTTGAGT
-TTGATAACTT TGCTGAAGTG CGCAAACTCT ATGAAGGTGG AGTTACACTA
-CCTACAAACT TTCTTAGCAA GATCGCCCCT ATACCAGTGG TCAAGGAAAT
-TTTTCGAACT GATGGCGAAC AGTTCCTCAA GTATCCACCA CCTAAAGTGA
-TGCAGGGTAT GCTACATATT TTGAATATGT AGAATATTAT CAATATACTC
-CTGTTTTTAT TCAACATATT TAATCACATG GATGAATTTT TGAACTGTTA';
+    $default_example_sequence = variable_get('blast_ui_nucleotide_example_sequence', 'sample');
   }
   elseif ($sequence_type == 'protein') {
-    $default_example_sequence = '>gi|166477|gb|AAA96434.1| resveratrol synthase [Arachis hypogaea]
-MVSVSGIRKVQRAEGPATVLAIGTANPPNCIDQSTYADYYFRVTNSEHMTDLKKKFQRICERTQIKNRHM
-YLTEEILKENPNMCAYKAPSLDAREDMMIREVPRVGKEAATKAIKEWGQPMSKITHLIFCTTSGVALPGV
-DYELIVLLGLDPCVKRYMMYHQGCFAGGTVLRLAKDLAENNKDARVLIVCSENTAVTFRGPSETDMDSLV
-GQALFADGAAAIIIGSDPVPEVEKPIFELVSTDQKLVPGSHGAIGGLLREVGLTFYLNKSVPDIISQNIN
-DALNKAFDPLGISDYNSIFWIAHPGGRAILDQVEQKVNLKPEKMKATRDVLSNYGNMSSACVFFIMDLMR
-KRSLEEGLKTTGEGLDWGVLFGFGPGLTIETVVLRSVAI';
+    $default_example_sequence = variable_get('blast_ui_protein_example_sequence', 'sample');
   }
   else {
-    $default_example_sequence = '';
+    $default_example_sequence = 'unknown query type';
   }
 
   // If the Show Example checkbox is true then put the example in the textfield
@@ -313,5 +279,24 @@ KRSLEEGLKTTGEGLDWGVLFGFGPGLTIETVVLRSVAI';
   }
 
   return $form['query']['FASTA'];
+}
+
 
-}
+/**
+ * Enable web services API
+ *
+ * @param $owner
+ *   
+ * @param $api
+ *
+ * @return $result
+ *  
+ */
+function blast_ui_ctools_plugin_api($owner, $api) {
+  if ($owner == 'services' && $api == 'services') {
+    return array(
+      'version' => 3,
+      'file' => 'includes/blast_ui.services.inc'
+    );
+  }
+}

+ 1 - 1
includes/blast_ui.admin.inc

@@ -136,7 +136,7 @@ function blast_ui_admin_form_validate($form, &$form_state) {
  *
  */
 function blast_ui_admin_form_submit($form, $form_state) {
-
+  variable_set('blast_path', $form_state['values']['blast_path']);
   variable_set('blast_ui_allow_target_upload', $form_state['values']['target_upload']);
 	variable_set('blast_threads', $form_state['values']['blast_threads']);
   variable_set('blast_ui_nucleotide_example_sequence', $form_state['values']['nucleotide_example']);

+ 129 - 0
includes/blast_ui.custom.inc

@@ -0,0 +1,129 @@
+<?php
+/*
+ * customized for PeanutBase
+ *
+ */
+ 
+function tripal_custom_generate_linkout($url_prefix, $hit, $info, $options = array()) {
+// uncomment to see contents of hit object
+//echo "hit:<pre>";var_dump($hit);echo "</pre>";
+// uncomment to see contents of info object
+//echo "info:<pre>";var_dump($info);echo "</pre>";
+
+  $url = false;
+  $hit_name = $hit->{'Hit_def'};
+//echo "hit name: $hit_name ... ";
+
+  if ($info['Target'] == 'All genomes') {
+    // default regex
+    $regex = "/^\w+\.(\S+).*/";
+    
+    if (preg_match('/^aradu/', $hit_name) == 1) {
+      $blastdb_name = 'PeanutBase_aradu_gbrowse';
+    }
+    else if (preg_match('/^araip/', $hit_name) == 1) {
+      $blastdb_name = 'PeanutBase_araip_gbrowse';
+    }
+    else if (preg_match('/^cajca/', $hit_name) == 1) {
+      $blastdb_name = 'LegumeInfo_cajca_gbrowse';
+    }
+    else if (preg_match('/^cicar/', $hit_name) == 1) {
+      $blastdb_name = 'LegumeInfo_cicar_gbrowse';
+    }
+    else if (preg_match('/^glyma/', $hit_name) == 1) {
+      $blastdb_name = 'SoyBase_glyma_gbrowse';
+    }
+    else if (preg_match('/^lotja/', $hit_name) == 1) {
+      $blastdb_name = 'LegumeInfo_lotja_gbrowse';
+    }
+    else if (preg_match('/^medtr/', $hit_name) == 1) {
+      $blastdb_name = 'LegumeInfo_medtr_gbrowse';
+    }
+    else if (preg_match('/^phavu/', $hit_name) == 1) {
+      $blastdb_name = 'LegumeInfo_phavu_gbrowse';
+    }
+    else if (preg_match('/^vigra/', $hit_name) == 1) {
+      $blastdb_name = 'LegumeInfo_vigra_gbrowse';
+    }
+    else {
+      // Don't know what to do with this hit
+      drupal_set_message("Don't know how to create GBrowse linkout for $hit_name", 'error');
+    }  
+
+    $hit_name = preg_replace($regex, '$1', $hit_name);
+    $hit->{'linkout_id'} = $hit_name;
+    if ($blastdb_info = tripal_custom_getBLASTdbinfo($blastdb_name)) {
+//echo "generate gbrowse link with " . $blastdb_info['urlprefix'] . " $hit<br>";
+      $url = tripal_blast_generate_linkout_gbrowse($blastdb_info['urlprefix'], $hit, $info, $options);
+    }
+  }//handle All genomes BLAST target
+  
+  else {
+    // default regex:
+    $regex = "/^\w+\.(\S+)/";
+    
+    if (preg_match('/^aradu/', $hit_name) == 1) {
+      $blastdb_name = 'PeanutBase_aradu_gene';
+    }
+    else if (preg_match('/^araip/', $hit_name) == 1) {
+      $blastdb_name = 'PeanutBase_araip_gene';
+    }
+    else if (preg_match('/^cajca/', $hit_name) == 1) {
+      $blastdb_name = 'LegumeInfo_cajca_gene';
+    }
+    else if (preg_match('/^cicar/', $hit_name) == 1) {
+      $blastdb_name = 'LegumeInfo_cicar_gene';
+    }
+    else if (preg_match('/^glyma/', $hit_name) == 1) {
+      $blastdb_name = 'LegumeInfo_glyma_gene';
+      if (preg_match("/^\w+\.(\S+)\.p/", $hit_name)) {
+        //glyma protein
+        $regex = "/^\w+\.(\S+)\.p/";
+      }
+    }
+    else if (preg_match('/^lotja/', $hit_name) == 1) {
+      $blastdb_name = 'LegumeInfo_lotja_gene';
+    }
+    else if (preg_match('/^medtr/', $hit_name) == 1) {
+      $blastdb_name = 'LegumeInfo_medtr_gene';
+    }
+    else if (preg_match('/^phavu/', $hit_name) == 1) {
+      $blastdb_name = 'LegumeInfo_phavu_gene';
+    }
+    else if (preg_match('/^vigra/', $hit_name) == 1) {
+      $blastdb_name = 'LegumeInfo_vigra_gene';
+    }
+    else {
+      // Don't know what to do with this hit
+      drupal_set_message("Don't know how to create linkout for $hit_name", 'error');
+    }  
+
+    $hit_name = preg_match($regex, $hit_name, $matches);
+//echo "<br>Using $regex, found matches:<pre>" . var_dump($matches);echo "</pre>";
+//echo "<br>Use [" . $matches[1] . "]<br>";
+    $hit->{'linkout_id'} = $matches[1];
+//echo "look for gene link for $blastdb_name with " . $hit->{'linkout_id'} . "<br>";
+    if ($blastdb_info = tripal_custom_getBLASTdbinfo($blastdb_name)) {
+//echo "generate gbrowse link with " . $blastdb_info['urlprefix'] . " $hit<br>";
+      $url = tripal_blast_generate_linkout_link($blastdb_info['urlprefix'], $hit, $info, $options);
+    }
+  }
+  return $url;
+}
+
+
+function tripal_custom_getBLASTdbinfo($blastdb_name) {
+  $sql = "
+    SELECT urlprefix 
+    FROM {db} WHERE name='$blastdb_name'";
+//echo "$sql<br>";
+  if ($res = chado_query($sql)) {
+    if ($row=$res->fetchObject()) {
+      return array(
+        'urlprefix' => $row->urlprefix, 
+      );
+    }
+  }
+  
+  return false;
+}//tripal_custom_getBLASTdbinfo

+ 493 - 242
includes/blast_ui.form_advanced_options.inc

@@ -23,6 +23,16 @@
  *   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 = base64_decode($_GET['jid']);
+     $job_data = $all_job_data[$jid];
+  }
+  else {
+    $job_data = array();
+    $jid = 0;
+  }
+  $defaults = _get_default_values($job_data, 'blastn');
 
   // General parameters
   //.........................
@@ -36,58 +46,40 @@ function blast_ui_blastn_advanced_options_form(&$form, $form_state) {
   $form['ALG']['GParam']['maxTarget'] = array(
     '#type' => 'select',
     '#title' => t('Max target sequences:'),
-    '#options' => array(
-      0 => t('10'),
-      1 => t('50'),
-      2 => t('100'),
-      3 => t('250'),
-      4 => t('500'),
-      5 => t('1000'),
-      6 => t('5000'),
-      7 => t('10000'),
-      8 => t('20000'),
-    ),
-    '#default_value' => 2,
+    '#options' => _get_max_target('blastn'),
+    '#default_value' => $defaults['max_target_seqs'],
     '#description' => t('Select the maximum number of aligned sequences to display'),
   );
 
+/*eksc- remove until we learn how this is implemented by NCBI
   $form['ALG']['GParam']['shortQueries'] = array(
     '#type' => 'checkbox',
     '#title' => t('Automatically adjust parameters for short input sequences'),
-    '#default_value' => TRUE,
+    '#default_value' => $short_queries,
   );
+*/
 
   $form['ALG']['GParam']['eVal'] = array(
     '#type' => 'textfield',
     '#title' => t('e-Value (Expected Threshold)'),
-    '#default_value' => 10,
+    '#default_value' => $defaults['evalue'],
     '#size' => 12,
     '#maxlength' => 20,
-    '#description' => t('Expected number of chance matches in a random model. This number should be give in a decimal format. <a href="http://www.ncbi.nlm.nih.gov/BLAST/blastcgihelp.shtml#expect" target="_blank">More Information</a> | <a href="https://www.youtube.com/watch?v=nO0wJgZRZJs" target="_blank">Expect value vedio tutorial</a>'),
+    '#description' => t('Expected number of chance matches in a random model. This number should be give in a decimal format. <a href="http://www.ncbi.nlm.nih.gov/BLAST/blastcgihelp.shtml#expect" target="_blank">More Information</a> | <a href="https://www.youtube.com/watch?v=nO0wJgZRZJs" target="_blank">Expect value video tutorial</a>'),
   );
 
   $form['ALG']['GParam']['wordSize'] = array(
     '#type' => 'select',
     '#title' => t('Word size:'),
-    '#options' => array(
-      0 => t('16'),
-      1 => t('20'),
-      2 => t('24'),
-      3 => t('28'),
-      4 => t('32'),
-      5 => t('48'),
-      6 => t('64'),
-      7 => t('128'),
-      8 => t('256'),
-    ),
-    '#default_value' => 3,
+    '#options' => _get_word_size('blastn'),
+    '#default_value' => $defaults['word_size'],
     '#description' => t('The length of the seed that initiates an alignment'),
   );
 
   $form['ALG']['GParam']['qRange'] = array(
     '#type' => 'textfield',
     '#title' => t('Max matches in a query range'),
-    '#default_value' => 0,
+    '#default_value' => $defaults['qRange'],
     '#size' => 12,
     '#maxlength' => 20,
     '#description' => t('Limit the number of matches to a query range. This option is useful if many strong matches to one part of a query may prevent BLAST from presenting weaker matches to another part of the query.'),
@@ -105,34 +97,18 @@ function blast_ui_blastn_advanced_options_form(&$form, $form_state) {
   $form['ALG']['SParam']['M&MScores'] = array(
     '#type' => 'select',
     '#title' => t('Match/Mismatch Scores:'),
-    '#options' => array(
-       0 => t('1,-2'),
-       1 => t('1,-3'),
-       2 => t('1,-4'),
-       3 => t('2,-3'),
-       4 => t('4,-5'),
-       5 => t('1,-1'),
-     ),
-    '#default_value' => 0,
+    '#options' => _get_match_mismatch('blastn'),
+    '#default_value' => $defaults['matchmiss'],
     '#description' => t('Reward and penalty for matching and mismatching bases.'),
    );
 
    $form['ALG']['SParam']['gapCost'] = array(
     '#type' => 'select',
     '#title' => t('Gap Costs:'),
-    '#options' => array(
-      0 => t('Existence: 5 Extension: 2'),
-      1 => t('Existence: 2 Extension: 2'),
-      2 => t('Existence: 1 Extension: 2'),
-      3 => t('Existence: 0 Extension: 2'),
-      4 => t('Existence: 3 Extension: 1'),
-      5 => t('Existence: 2 Extension: 1'),
-      6 => t('Existence: 1 Extension: 1'),
-    ),
-    '#default_value' => 0,
+    '#options' => _get_gap('blastn'),
+    '#default_value' => $defaults['gap'],
     '#description' => t('Cost to create and extend a gap in an alignment. Linear costs are available only with megablast and are determined by the match/mismatch scores.'),
   );
-
 }
 
 /**
@@ -148,7 +124,6 @@ function blast_ui_blastn_advanced_options_form_validate($form, $form_state) { }
  * @see blast_ui_blastn_advanced_options_form().
  */
 function blast_ui_blastn_advanced_options_form_submit($form, $form_state) {
-
   $eVal = $form_state['values']['eVal'];
 
   $trgtKey = $form_state['values']['maxTarget'];
@@ -158,77 +133,25 @@ function blast_ui_blastn_advanced_options_form_submit($form, $form_state) {
   $wordSize = $form['ALG']['GParam']['wordSize']['#options'][$wsKey];
 
   // Expand Gap Cost key into open and extend penalties
-  $gapKey = $form_state['values']['gapCost'];
-  switch ($gapKey) {
-   case 0:
-      $gapOpen = 5;
-      $gapExtend = 2;
-      break;
-   case 1:
-      $gapOpen = 2;
-      $gapExtend = 2;
-      break;
-   case 2:
-      $gapOpen = 1;
-      $gapExtend = 2;
-      break;
-   case 3:
-      $gapOpen = 0;
-      $gapExtend = 2;
-      break;
-   case 4:
-      $gapOpen = 3;
-      $gapExtend = 1;
-      break;
-   case 5:
-      $gapOpen = 2;
-      $gapExtend = 1;
-      break;
-   case 6:
-      $gapOpen = 1;
-      $gapExtend = 1;
-      break;
-  }
+  $gap = _set_gap($form_state['values']['gapCost']);
 
-  // Epand Match/Mismatch option into penalty/reward values
-  // @todo Amir: Is the switch supposed to be for $scoreKey?
-  $scoreKey = $form_state['values']['M&MScores'];
-  switch ($gapKey) {
-   case 0:
-      $penalty = -2;
-      $reward = 1;
-      break;
-   case 1:
-      $penalty = -3;
-      $reward = 1;
-      break;
-   case 2:
-      $penalty = -4;
-      $reward = 1;
-      break;
-   case 3:
-      $penalty = -3;
-      $reward = 2;
-      break;
-   case 4:
-      $penalty = -5;
-      $reward = 4;
-      break;
-   case 5:
-      $penalty = -1;
-      $reward = 1;
-      break;
-  }
+  // Expand Match/Mismatch option into penalty/reward values
+  $m_m = _set_match_mismatch($form_state['values']['M&MScores']);
+
+  // Limit number of query hits
+  $qRange = $form_state['values']['qRange'];
 
   return array(
-    'evalue' => $eVal,
-    'word_size' => $wordSize,
-    'gapopen' => $gapOpen,
-    'gapextend' => $gapExtend,
-    'penalty' =>  $penalty,
-    'reward' => $reward
+  	'max_target_seqs' => $numAlign,
+    'evalue'          => $eVal,
+    'word_size'       => $wordSize,
+    'gapopen'         => $gap['gapOpen'],
+    'gapextend'       => $gap['gapExtend'],
+    'penalty'         => $m_m['penalty'],
+    'reward'          => $m_m['reward'],
+    'culling_limit'   => $qRange,
   );
-}
+}//blast_ui_blastn_advanced_options_form_submit
 
 /**
  * @section
@@ -248,8 +171,18 @@ 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 = base64_decode($_GET['jid']);
+     $job_data = $all_job_data[$jid];
+  }
+  else {
+    $job_data = array();
+    $jid = 0;
+  }
+  $defaults = _get_default_values($job_data, 'blastx');
 
-  $form['ALG']['GParam'] = array(
+   $form['ALG']['GParam'] = array(
    '#type' => 'fieldset',
    '#title' => t('General parameters'),
    '#collapsible' => FALSE,
@@ -258,30 +191,82 @@ function blast_ui_blastx_advanced_options_form(&$form, $form_state) {
   $form['ALG']['GParam']['maxTarget'] = array(
     '#type' => 'select',
     '#title' => t('Max target sequences:'),
-    '#options' => array(
-      0 => t('10'),
-      1 => t('50'),
-      2 => t('100'),
-      3 => t('250'),
-      4 => t('500'),
-      5 => t('1000'),
-      6 => t('5000'),
-      7 => t('10000'),
-      8 => t('20000'),
-    ),
-    '#default_value' => 2,
+    '#options' => _get_max_target('blastx'),
+    '#default_value' => $defaults['max_target_seqs'],
     '#description' => t('Select the maximum number of aligned sequences to display'),
   );
 
   $form['ALG']['GParam']['eVal'] = array(
     '#type' => 'textfield',
     '#title' => t('e-Value (Expected Threshold)'),
-    '#default_value' => 10,
+    '#default_value' => $defaults['evalue'],
     '#size' => 12,
     '#maxlength' => 20,
     '#description' => t('Expected number of chance matches in a random model. This number should be give in a decimal format. <a href="http://www.ncbi.nlm.nih.gov/BLAST/blastcgihelp.shtml#expect" target="_blank">More Information</a> | <a href="https://www.youtube.com/watch?v=nO0wJgZRZJs" target="_blank">Expect value vedio tutorial</a>'),
   );
 
+/*eksc- need to learn how this is implemented for blastx
+  $form['ALG']['GParam']['shortQueries'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Automatically adjust parameters for short input sequences'),
+    '#default_value' => TRUE,
+  );
+*/
+
+  $form['ALG']['GParam']['wordSize'] = array(
+    '#type' => 'select',
+    '#title' => t('Word size:'),
+    '#options' => _get_word_size('blastx'),
+    '#default_value' => $defaults['word_size'],
+    '#description' => t('The length of the seed that initiates an alignment'),
+  );
+
+  // Scoring parameters
+  //.........................
+
+  $form['ALG']['SParam'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Scoring parameters'),
+    '#collapsible' => FALSE,
+  );
+
+  $matrix_options = _get_matrix_options();
+  $form['ALG']['SParam']['Matrix'] = array(
+    '#type' => 'select',
+    '#title' => 'Matrix',
+    '#options' => $matrix_options,
+    '#default_value' => $default['matrix'],
+    '#description' => t('Assigns a score for aligning pairs of residues, and determines overall alignment score..'),
+    '#ajax' => array(
+      'callback' => 'ajax_dependent_dropdown_callback',
+      'wrapper' => 'dropdown-second-replace',
+    ),
+  );
+
+  $form['ALG']['GParam']['qRange'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Max matches in a query range'),
+    '#default_value' => $defaults['qRange'],
+    '#size' => 12,
+    '#maxlength' => 20,
+    '#description' => t('Limit the number of matches to a query range. This option is useful if many strong matches to one part of a query may prevent BLAST from presenting weaker matches to another part of the query.'),
+  );
+
+/*eksc- NOT match/mismatch but instead computational adjustments; 
+        need to learn how there are implemented for blastx
+  $form['ALG']['SParam']['M&MScores'] = array(
+    '#type' => 'select',
+    '#title' => t('Match/Mismatch Scores:'),
+    '#options' => array(
+				0 => t('No adjustment'),
+				1 => t('Composition-based statistics'),
+				2 => t('Conditional compositional score matrix adjustment'),
+				3 => t('Universal composition score matrix adjustment '),
+			),
+    '#default_value' => 2,
+    '#description' => t('Matrix adjustment method to compensate for amino acid composition of sequences'),
+  );
+*/
 }
 
 /**
@@ -298,14 +283,8 @@ function blast_ui_blastx_advanced_options_form_validate($form, $form_state) { }
  */
 function blast_ui_blastx_advanced_options_form_submit($form, $form_state) {
 
-  $eVal = $form_state['values']['eVal'];
-
-  $trgtKey = $form_state['values']['maxTarget'];
-  $numAlign = $form['ALG']['GParam']['maxTarget']['#options'][$trgtKey];
-
-  return array(
-    'evalue' => $eVal,
-  );
+  // Same as blastp form submit
+  return blast_ui_blastp_advanced_options_form_submit($form, $form_state);
 
 }
 
@@ -327,6 +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 = base64_decode($_GET['jid']);
+     $job_data = $all_job_data[$jid];
+  }
+  else {
+    $job_data = array();
+    $jid = 0;
+  }
+  $defaults = _get_default_values($job_data, 'blastp');
 
   //General parameters
 
@@ -339,54 +328,43 @@ function blast_ui_blastp_advanced_options_form(&$form, $form_state) {
   $form['ALG']['GParam']['maxTarget'] = array(
     '#type' => 'select',
     '#title' => t('Max target sequences:'),
-    '#options' => array(
-       0 => t('10'),
-       1 => t('50'),
-       2 => t('100'),
-       3 => t('250'),
-       4 => t('500'),
-       5 => t('1000'),
-       6 => t('5000'),
-       7 => t('10000'),
-       8 => t('20000'),
-    ),
-    '#default_value' => 2,
+    '#options' => _get_max_target('blastp'),
+    '#default_value' => $defaults['max_target_seqs'],
     '#description' => t('Select the maximum number of aligned sequences to display'),
   );
 
+/*eksc- remove until we learn how this is implemented
   $form['ALG']['GParam']['shortQueries'] = array(
    '#type' => 'checkbox',
    '#title' => t('Automatically adjust parameters for short input sequences'),
    '#default_value' => TRUE,
   );
+*/
 
   $form['ALG']['GParam']['eVal'] = array(
-  	'#type' => 'textfield',
-  	'#title' => t('e-value(Expect threshold)'),
-  	'#default_value' => 10,
-  	'#size' => 12,
-  	'#maxlength' => 20,
-  	'#description' => t('Expected number of chance matches in a random model.'),
+    '#type' => 'textfield',
+    '#title' => t('e-value(Expect threshold)'),
+    '#default_value' => $defaults['evalue'],
+    '#size' => 12,
+    '#maxlength' => 20,
+    '#description' => t('Expected number of chance matches in a random model.'),
   );
 
   $form['ALG']['GParam']['wordSize'] = array(
     '#type' => 'select',
     '#title' => t('Word size:'),
-    '#options' => array(
-       0 => t('2'),
-       1 => t('3'),
-    ),
-    '#default_value' => 1,
+    '#options' => _get_word_size('blastp'),
+    '#default_value' => $defaults['word_size'],
     '#description' => t('The length of the seed that initiates an alignment'),
   );
 
   $form['ALG']['GParam']['qRange'] = array(
-   '#type' => 'textfield',
-   '#title' => t('Max matches in a query range'),
-   '#default_value' => 0,
-   '#size' => 12,
-   '#maxlength' => 20,
-   '#description' => t('Limit the number of matches to a query range. This option is useful if many strong matches to one part of a query may prevent BLAST from presenting weaker matches to another part of the query.'),
+    '#type' => 'textfield',
+    '#title' => t('Max matches in a query range'),
+    '#default_value' => $defaults['qRange'],
+    '#size' => 12,
+    '#maxlength' => 20,
+    '#description' => t('Limit the number of matches to a query range. This option is useful if many strong matches to one part of a query may prevent BLAST from presenting weaker matches to another part of the query.'),
   );
 
   // Scoring parameters
@@ -397,31 +375,33 @@ function blast_ui_blastp_advanced_options_form(&$form, $form_state) {
    '#collapsible' => FALSE,
   );
 
-  $options_first = _ajax_example_get_first_dropdown_options();
-  $selected = isset($form_state['values']['MATRIX'] ) ? $form_state['values']['MATRIX'] : key($options_first);
-
-  $form['ALG']['SParam']['MATRIX'] = array(
+  $matrix_options = _get_matrix_options();
+  $form['ALG']['SParam']['Matrix'] = array(
     '#type' => 'select',
     '#title' => 'Matrix',
-    '#options' => $options_first,
-    '#default_value' => $selected,
+    '#options' => $matrix_options,
+    '#default_value' => $defaults['matrix'],
     '#description' => t('Assigns a score for aligning pairs of residues, and determines overall alignment score..'),
     '#ajax' => array(
-      'callback' => 'ajax_example_dependent_dropdown_callback',
+      'callback' => 'ajax_dependent_dropdown_callback',
       'wrapper' => 'dropdown-second-replace',
     ),
   );
 
+/*eksc- probably not used for blastp
   $form['ALG']['SParam']['gapCost'] = array(
     '#type' => 'select',
     '#title' => t('Gap Costs:'),
     '#prefix' => '<div id="dropdown-second-replace">',
     '#suffix' => '</div>',
-    '#options' => _ajax_example_get_second_dropdown_options($selected),
+    '#options' => _get_gap_for_matrix($selected),
     '#default_value' => 2,
     '#description' => t('Cost to create and extend a gap in an alignment.'),
   );
+*/
 
+/*eksc- NOT match/mismatch but instead computational adjustments; 
+        need to learn how there are implemented for blastp
   $form['ALG']['SParam']['M&MScores'] = array(
     '#type' => 'select',
     '#title' => t('Match/Mismatch Scores:'),
@@ -434,11 +414,11 @@ function blast_ui_blastp_advanced_options_form(&$form, $form_state) {
     '#default_value' => 2,
     '#description' => t('Matrix adjustment method to compensate for amino acid composition of sequences'),
   );
-
-}
+*/
+}//blast_ui_blastp_advanced_options_form
 
 /**
- * Validate the advanced options provided by the BLASTn form above.
+ * Validate the advanced options provided by the BLASTp form above.
  *
  * @see blast_ui_blastp_advanced_options_form().
  */
@@ -459,11 +439,12 @@ function blast_ui_blastp_advanced_options_form_submit($form, $form_state) {
   $wsKey = $form_state['values']['wordSize'];
   $wordSize = $form['ALG']['GParam']['wordSize']['#options'][$wsKey];
 
+  $qRange = $form_state['values']['qRange'];
+  
   // Expand Gap Cost key into open and extend penalties
-  $gapKey = $form_state['values']['MATRIX'];
-  switch ($gapKey) {
-   case 0:
-     $matrix ="PAM30";
+  $matrix = $form_state['values']['Matrix'];
+  switch ($matrix) {
+   case 'PAM30':
      $gapKey = $form_state['values']['gapCost'];
      switch ($gapKey) {
       case 0:
@@ -492,8 +473,7 @@ function blast_ui_blastp_advanced_options_form_submit($form, $form_state) {
          break;
      }
      break;
-   case 1:
-     $matrix ="PAM70";
+   case 'PAM70':
      $gapKey = $form_state['values']['gapCost'];
      switch ($gapKey) {
       case 0:
@@ -522,8 +502,7 @@ function blast_ui_blastp_advanced_options_form_submit($form, $form_state) {
          break;
      }
      break;
-   case 2:
-     $matrix ="PAM250";
+   case 'PAM250':
      $gapKey = $form_state['values']['gapCost'];
      switch ($gapKey) {
       case 0:
@@ -588,8 +567,7 @@ function blast_ui_blastp_advanced_options_form_submit($form, $form_state) {
          break;
      }
      break;
-   case 3:
-     $matrix ="BLOSUM80";
+   case 'BLOSUM80':
      $gapKey = $form_state['values']['gapCost'];
      switch ($gapKey) {
       case 0:
@@ -618,8 +596,7 @@ function blast_ui_blastp_advanced_options_form_submit($form, $form_state) {
          break;
      }
       break;
-   case 4:
-     $matrix ="BLOSUM62";
+   case 'BLOSUM62':
      $gapKey = $form_state['values']['gapCost'];
      switch ($gapKey) {
       case 0:
@@ -668,8 +645,7 @@ function blast_ui_blastp_advanced_options_form_submit($form, $form_state) {
          break;
      }
       break;
-   case 5:
-     $matrix ="BLOSUM45";
+   case 'BLOSUM45':
      $gapKey = $form_state['values']['gapCost'];
      switch ($gapKey) {
       case 0:
@@ -722,8 +698,7 @@ function blast_ui_blastp_advanced_options_form_submit($form, $form_state) {
          break;
      }
      break;
-   case 6:
-     $matrix ="BLOSUM50";
+   case 'BLOSUM50':
      $gapKey = $form_state['values']['gapCost'];
      switch ($gapKey) {
       case 0:
@@ -788,8 +763,7 @@ function blast_ui_blastp_advanced_options_form_submit($form, $form_state) {
          break;
      }
      break;
-   case 7:
-     $matrix ="BLOSUM90";
+   case 'BLOSUM90':
      $gapKey = $form_state['values']['gapCost'];
      switch ($gapKey) {
       case 0:
@@ -823,42 +797,47 @@ function blast_ui_blastp_advanced_options_form_submit($form, $form_state) {
      }
      break;
   }
+  
+//eksc- need to implement query range limit
+//  q_range
 
   return array(
-    'evalue' => $eVal,
-    'word_size' => $wordSize,
-    'gapopen' => $gapOpen,
-    'gapextend' => $gapExtend,
-    'matrix' => $matrix
+  	'max_target_seqs' => $numAlign,
+    'evalue'          => $eVal,
+    'word_size'       => $wordSize,
+    'gapopen'         => $gapOpen,
+    'gapextend'       => $gapExtend,
+    'culling_limit'   => $qRange,
+    'matrix'          => $matrix,
   );
-}
+}//blast_ui_blastp_advanced_options_form_submit
 
 /**
- * Fill the first dropdown list with appropriate options
+ * Fill the matrix dropdown list with appropriate options
  *
  * @return
  * An array consisting of matrices name for the first dropdown list
  */
-function _ajax_example_get_first_dropdown_options() {
+function _get_matrix_options() {
   return drupal_map_assoc(array(
-  t('PAM30'),
-  t('PAM70'),
-  t('PAM250'),
-  t('BLOSUM80'),
-  t('BLOSUM62'),
-  t('BLOSUM45'),
-  t('BLOSUM50'),
-  t('BLOSUM90'),
+		t('PAM30'),
+		t('PAM70'),
+		t('PAM250'),
+		t('BLOSUM80'),
+		t('BLOSUM62'),
+		t('BLOSUM45'),
+		t('BLOSUM50'),
+		t('BLOSUM90'),
   ));
 }
 
 /**
- * Fill the second dropdown list with appropriate options
+ * Fill the gap penalty dropdown list with appropriate options given selected matrix
  *
  * @return
  * An array containing open and extension gap values for the chosen matrix (to fill the second dropdown list)
  */
-function _ajax_example_get_second_dropdown_options($key = '') {
+function _get_gap_for_matrix($key = '') {
   $options = array(
     t('PAM30') => drupal_map_assoc(array(
       t('Existence: 7 Extension: 2'),
@@ -954,18 +933,20 @@ function _ajax_example_get_second_dropdown_options($key = '') {
       t('Existence: 10 Extension: 1'),
       t('Existence: 9 Extension: 1'),
     )),
-    );
-    if (isset($options[$key])) {
-    	return $options[$key];
-    } else {
-    	return array();
-    }
-}
+  );
+  
+	if (isset($options[$key])) {
+		return $options[$key];
+	} 
+	else {
+		return array();
+	}
+}//_get_gap_for_matrix
 
 /**
  * Respond to Ajax dropdown call
  */
-function ajax_example_dependent_dropdown_callback($form, $form_state) {
+function ajax_dependent_dropdown_callback($form, $form_state) {
   return $form['ALG']['SParam']['gapCost'];
 }
 
@@ -987,6 +968,16 @@ function ajax_example_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 = base64_decode($_GET['jid']);
+     $job_data = $all_job_data[$jid];
+  }
+  else {
+    $job_data = array();
+    $jid = 0;
+  }
+  $defaults = _get_default_values($job_data, 'tblastn');
 
   $form['ALG']['GParam'] = array(
    '#type' => 'fieldset',
@@ -997,53 +988,313 @@ function blast_ui_tblastn_advanced_options_form(&$form, $form_state) {
   $form['ALG']['GParam']['maxTarget'] = array(
     '#type' => 'select',
     '#title' => t('Max target sequences:'),
-    '#options' => array(
-      0 => t('10'),
-      1 => t('50'),
-      2 => t('100'),
-      3 => t('250'),
-      4 => t('500'),
-      5 => t('1000'),
-      6 => t('5000'),
-      7 => t('10000'),
-      8 => t('20000'),
-    ),
-    '#default_value' => 2,
+    '#options' => _get_max_target('tblastn'),
+    '#default_value' => $defaults['max_target_seqs'],
     '#description' => t('Select the maximum number of aligned sequences to display'),
   );
 
   $form['ALG']['GParam']['eVal'] = array(
     '#type' => 'textfield',
     '#title' => t('e-Value (Expected Threshold)'),
-    '#default_value' => 10,
+    '#default_value' => $defaults['evalue'],
     '#size' => 12,
     '#maxlength' => 20,
     '#description' => t('Expected number of chance matches in a random model. This number should be give in a decimal format. <a href="http://www.ncbi.nlm.nih.gov/BLAST/blastcgihelp.shtml#expect" target="_blank">More Information</a> | <a href="https://www.youtube.com/watch?v=nO0wJgZRZJs" target="_blank">Expect value vedio tutorial</a>'),
   );
 
-}
+/*eksc- need to learn how this is implemented for tblastn
+  $form['ALG']['GParam']['shortQueries'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Automatically adjust parameters for short input sequences'),
+    '#default_value' => TRUE,
+  );
+*/
+
+  $form['ALG']['GParam']['wordSize'] = array(
+    '#type' => 'select',
+    '#title' => t('Word size:'),
+    '#options' => _get_word_size('tblastn'),
+    '#default_value' => $defaults['word_size'],
+    '#description' => t('The length of the seed that initiates an alignment'),
+  );
+
+  // Scoring parameters
+  //.........................
+
+  $form['ALG']['SParam'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Scoring parameters'),
+    '#collapsible' => FALSE,
+  );
+
+  $matrix_options = _get_matrix_options();
+  $form['ALG']['SParam']['Matrix'] = array(
+    '#type' => 'select',
+    '#title' => 'Matrix',
+    '#options' => $matrix_options,
+    '#default_value' => $defaults['matrix'],
+    '#description' => t('Assigns a score for aligning pairs of residues, and determines overall alignment score..'),
+    '#ajax' => array(
+      'callback' => 'ajax_dependent_dropdown_callback',
+      'wrapper' => 'dropdown-second-replace',
+    ),
+  );
+
+  $form['ALG']['SParam']['gapCost'] = array(
+    '#type' => 'select',
+    '#title' => t('Gap Costs:'),
+    '#prefix' => '<div id="dropdown-second-replace">',
+    '#suffix' => '</div>',
+    '#options' => _get_gap_for_matrix($$default['matrix']),
+    '#default_value' => 2,
+    '#description' => t('Cost to create and extend a gap in an alignment.'),
+  );
+
+  $form['ALG']['GParam']['qRange'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Max matches in a query range'),
+    '#default_value' => $defaults['qRange'],
+    '#size' => 12,
+    '#maxlength' => 20,
+    '#description' => t('Limit the number of matches to a query range. This option is useful if many strong matches to one part of a query may prevent BLAST from presenting weaker matches to another part of the query.'),
+  );
+}//blast_ui_tblastn_advanced_options_form
 
 /**
- * Validate the advanced options provided by the BLASTn form above.
+ * Validate the advanced options provided by the tBLASTn form above.
  *
  * @see blast_ui_tblastn_advanced_options_form().
  */
 function blast_ui_tblastn_advanced_options_form_validate($form, $form_state) { }
 
 /**
- * Processed the advanced options provided by the yBLASTn form above.
+ * Processed the advanced options provided by the tBLASTn form above.
  *
  * @see blast_ui_tblastn_advanced_options_form().
  */
 function blast_ui_tblastn_advanced_options_form_submit($form, $form_state) {
 
-  $eVal = $form_state['values']['eVal'];
+  return blast_ui_blastp_advanced_options_form_submit($form, $form_state);
 
-  $trgtKey = $form_state['values']['maxTarget'];
-  $numAlign = $form['ALG']['GParam']['maxTarget']['#options'][$trgtKey];
+}
 
+/*
+ * Get default form values; may come from saved job data if user is re-running
+ *   a previous job.
+ */
+function _get_default_values($job_data) {
+  // 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;
+
+  $matchmiss = 0;
+  $reward = (isset($job_data['options']['reward'])) 
+  					? $job_data['options']['reward'] : 1;
+  $penalty = (isset($job_data['options']['penalty'])) 
+  					? $job_data['options']['penalty'] : -2;
+  if ($reward == 1) {
+  	switch ($penalty) {
+  		case -1: $matchmiss = 5; break;
+  	  case -2: $matchmiss = 0; break;
+  	  case -3: $matchmiss = 1; break;
+  	  case -4: $matchmiss = 2; break;
+  	}
+  }
+  else if ($reward == 2) {
+  	$matchmiss = 3;
+  }
+  else if ($reward == 3) {
+  	 $matchmis = 4;
+  }
+  else if ($eward == 4) {
+  	 $matchmiss = 5;
+  }
+  
+  $gap = 0;
+  $gapopen = (isset($job_data['options']['gapopen'])) 
+  					? $job_data['options']['gapopen'] : 5;
+  $gapextend = (isset($job_data['options']['gapextend'])) 
+  					? $job_data['options']['gapextend'] : 2;
+  if ($gapextend == 2) {
+  	switch ($gapopen) {
+  		case 5: $gap = 0; break;
+  		case 2: $gap = 1; break;
+  		case 1: $gap = 2; break;
+  		case 0: $gap = 3; break;
+  	}
+  }
+  else if ($gapextend == 1) {
+  	switch ($gapopen) {
+  		case 3: $gap = 4;
+  		case 2: $gap = 5;
+  		case 1: $gap = 6;
+  	}
+  }
+  
+// eksc- need to implement query range limit
+//  $q_range = 0;
+  
+  $matrix = (isset($job_data['options']['matrix'])) 
+  					? $job_data['options']['matrix'] : 'PAM30';
   return array(
-    'evalue' => $eVal,
+  	'max_target_seqs' => $max_target,
+  	'short_queries'   => $short_queries,
+  	'word_size'       => $word_size,
+  	'evalue'          => $evalue,
+  	'matchmiss'       => $matchmiss,
+  	'gap'             => $gap,
+  	'qRange'          => $qRange,
+    'matrix'          => $matrix,
   );
+}//_get_default_values
+
+function _get_max_target($which) {
+	switch ($which) {
+	  case 'blastn':
+	  case 'blastx':
+	  case 'blastp':
+	  case 'tblastn':
+			return array(
+				10 => t('10'),
+				50 => t('50'),
+				100 => t('100'),
+				250 => t('250'),
+				500 => t('500'),
+				1000 => t('1000'),
+				5000 => t('5000'),
+				10000 => t('10000'),
+				20000 => t('20000'),
+			);
+	}//switch
+}
+
+function _get_word_size($which) {
+	switch ($which) {
+		case 'blastn':
+			 return array(
+				 7 => t('7'),  
+				 11 => t('11'),
+				 15 => t('15'),
+				 16 => t('16'),
+				 20 => t('20'),
+				 24 => t('24'),
+				 28 => t('28'),
+				 32 => t('32'),
+				 48 => t('48'),
+				 64 => t('64'),
+			 	 128 => t('128'),
+				 256 => t('256'),
+	    );
+    case 'blastx':
+    case 'blastp':
+    case 'tblastn':
+    	return array(
+        2 => t('2'),
+        3 => t('3'),
+        6 => t('6'),
+      );
+	}//switch
+}
+
+function _get_match_mismatch($which) {
+	switch ($which) {
+		case 'blastn':
+      return array(
+				 0 => t('1,-2'),
+				 1 => t('1,-3'),
+				 2 => t('1,-4'),
+				 3 => t('2,-3'),
+				 4 => t('4,-5'),
+				 5 => t('1,-1'),
+      );
+  }//switch
+}
 
+function _get_gap($which) {
+	switch ($which) {
+		case 'blastn':
+      return array(
+				0 => t('Existence: 5 Extension: 2'),
+				1 => t('Existence: 2 Extension: 2'),
+				2 => t('Existence: 1 Extension: 2'),
+				3 => t('Existence: 0 Extension: 2'),
+				4 => t('Existence: 3 Extension: 1'),
+				5 => t('Existence: 2 Extension: 1'),
+				6 => t('Existence: 1 Extension: 1'),
+      );
+   }//switch
 }
+
+function _set_gap($gap_key) {
+ switch ($gap_key) {
+   case 0:
+      $gapOpen = 5;
+      $gapExtend = 2;
+      break;
+   case 1:
+      $gapOpen = 2;
+      $gapExtend = 2;
+      break;
+   case 2:
+      $gapOpen = 1;
+      $gapExtend = 2;
+      break;
+   case 3:
+      $gapOpen = 0;
+      $gapExtend = 2;
+      break;
+   case 4:
+      $gapOpen = 3;
+      $gapExtend = 1;
+      break;
+   case 5:
+      $gapOpen = 2;
+      $gapExtend = 1;
+      break;
+   case 6:
+      $gapOpen = 1;
+      $gapExtend = 1;
+      break;
+  }//switch
+  
+  return array('gapOpen' => $gapOpen, 'gapExtend' => $gapExtend);
+}
+
+function _set_match_mismatch($m_m) {
+  switch ($m_m) {
+   case 0:
+      $penalty = -2;
+      $reward = 1;
+      break;
+   case 1:
+      $penalty = -3;
+      $reward = 1;
+      break;
+   case 2:
+      $penalty = -4;
+      $reward = 1;
+      break;
+   case 3:
+      $penalty = -3;
+      $reward = 2;
+      break;
+   case 4:
+      $penalty = -5;
+      $reward = 4;
+      break;
+   case 5:
+      $penalty = -1;
+      $reward = 1;
+      break;
+  }//switch
+  
+  return array('penalty' => $penalty, 'reward' => $reward);
+}

+ 142 - 96
includes/blast_ui.form_per_program.inc

@@ -15,20 +15,22 @@
  */
 function blast_ui_per_blast_program_form($form, $form_state) {
 
-	//  CSS support to the form
-	$form['#attached']['css'] = array(
-		drupal_get_path('module', 'blast_ui') . '/theme/css/form.css',
-	);
-	
+  //  CSS support to the form
+  $form['#attached']['css'] = array(
+    drupal_get_path('module', 'blast_ui') . '/theme/css/form.css',
+  );
+  
   // @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 = base64_decode($_GET['jid']);
-	}	else {
-			$job_data = array();
-			$jid = 0;
-	}
+  //   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 = base64_decode($_GET['jid']);
+  }  
+  else {
+    $job_data = array();
+    $jid = 0;
+  }
+  
   // Determine the BLAST program.
   $query_type = $form_state['build_info']['args'][0];
   $db_type = $form_state['build_info']['args'][1];
@@ -99,8 +101,8 @@ function blast_ui_per_blast_program_form($form, $form_state) {
     '#prefix' => '<span style="float: right;">',
     '#suffix' => '</span>',
     '#ajax' => array(
-    	'callback' => 'ajax_blast_ui_example_sequence_callback',
-    	'wrapper'  => 'fasta-textarea',
+      'callback' => 'ajax_blast_ui_example_sequence_callback',
+      'wrapper'  => 'fasta-textarea',
       'method'   => 'replace',
       'effect'   => 'fade',
     ),
@@ -111,18 +113,19 @@ 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' => isset($job_data[$jid]['fasta']) ? $job_data[$jid]['fasta'] : '',
     '#prefix' => '<div id="fasta-textarea">',
     '#suffix' => '</div>',
   );
 
+/*TODO: FIX THIS! Shouldn't come up if not selected in configuration
   // Upload a file as an alternative to enter a query sequence
   $form['#attributes']['enctype'] = 'multipart/form-data';
   $form['query']['UPLOAD'] = array(
-    '#title' => 'Or upload your own query FASTA:	',
+    '#title' => 'Or upload your own query FASTA:  ',
     '#type' => 'managed_file',
     '#description' => t('The file should be a plain-text FASTA
-(.fasta, .fna, .fa) file. In other words, it cannot have formatting as is the
+(.fasta, .fna, .fa, .fas) file. In other words, it cannot have formatting as is the
 case with MS Word (.doc, .docx) or Rich Text Format (.rtf). It cannot be greater
 than %max_size in size. <strong>Don\'t forget to press the Upload button before
 attempting to submit your BLAST.</strong>',
@@ -131,10 +134,11 @@ attempting to submit your BLAST.</strong>',
       )
     ),
     '#upload_validators' => array(
-      'file_validate_extensions' => array('fasta fna fa'),
+      'file_validate_extensions' => array('fasta fna fa fas'),
       'file_validate_size' => array(file_upload_max_size()),
     ),
   );
+*/
 
 
   // BLAST DATABASE
@@ -142,7 +146,7 @@ attempting to submit your BLAST.</strong>',
 
   $form['DB'] = array(
     '#type' => 'fieldset',
-    '#title' => t('Choose Search Set'),
+    '#title' => t('Choose Search Target'),
     '#description' => t('Choose from one of the %type BLAST databases listed '
       . 'below. You can also use the browse button to upload a file from your '
       . 'local disk. The file may contain a single sequence or a list of '
@@ -164,7 +168,7 @@ attempting to submit your BLAST.</strong>',
     // Upload a file as an alternative to selecting an existing BLAST database
     $form['#attributes']['enctype'] = 'multipart/form-data';
     $form['DB']['DBUPLOAD'] = array(
-      '#title' => 'Or upload your own dataset:	',
+      '#title' => 'Or upload your own dataset:  ',
       '#type' => 'managed_file',
       '#description' => t('The file should be a plain-text FASTA
   (.fasta, .fna, .fa) file. In other words, it cannot have formatting as is the
@@ -175,6 +179,7 @@ attempting to submit your BLAST.</strong>',
           '%max_size' => round(file_upload_max_size() / 1024 / 1024,1) . 'MB'
         )
       ),
+      '#default_value' => variable_get($db_file_id, ''),
       '#upload_validators' => array(
         'file_validate_extensions' => array('fasta fna fa'),
         'file_validate_size' => array(file_upload_max_size()),
@@ -206,6 +211,12 @@ attempting to submit your BLAST.</strong>',
     '#default_value' => ' BLAST ',
   );
 
+  // Recent jobs list
+  $form['recentjobs'] = array(
+     '#type' => 'fieldset',
+     '#prefix' => get_recent_jobs(),
+   );
+   
   return $form;
 }
 
@@ -216,7 +227,6 @@ attempting to submit your BLAST.</strong>',
  */
 function blast_ui_per_blast_program_form_validate($form, &$form_state) {
 
-
   $blast_program = $form_state['values']['blast_program'];
 
   $type = $form_state['values']['query_type'];
@@ -305,7 +315,8 @@ function blast_ui_per_blast_program_form_validate($form, &$form_state) {
     );
   }
 
-}
+}//blast_ui_per_blast_program_form_validate
+
 
 /**
  * Process the user options submitted via the blast program form.
@@ -317,29 +328,27 @@ function blast_ui_per_blast_program_form_submit($form, &$form_state) {
   $error = FALSE;
   $blast_program = $form_state['values']['blast_program'];
 
-    if ($form_state['values']['db_type'] == 'nucleotide') {
-      $mdb_type = 'nucl';
-      $file_suffix = '.nsq';
-    }
-    else {
-      $mdb_type = 'prot';
-      $file_suffix = '.psq';
-    }
+  if ($form_state['values']['db_type'] == 'nucleotide') {
+    $mdb_type = 'nucl';
+  }
+  else {
+    $mdb_type = 'prot';
+  }
 
   // If the query was submitted via the texrfield then create a file containing it
-  if ( isset($form_state['qFlag']) ) {
-    if ( $form_state['qFlag'] == 'seqQuery' ) {
+  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);
+      $query = '/tmp/' . date('YMd_His') . '_query.fasta';
+      file_put_contents ($query , $seq_content);
     }
-    elseif ( $form_state['qFlag'] == 'upQuery' ) {
+    elseif ($form_state['qFlag'] == 'upQuery') {
       $query = $form_state['upQuery_path'];
     }
   }
 
   // If the BLAST database was uploaded then use it to run the BLAST
-  if ( $form_state['dbFlag'] == 'upDB') {
+  if ($form_state['dbFlag'] == 'upDB') {
 
     // Since we only support using the -db flag (not -subject) we need to create a
     // blast database for the FASTA uploaded.
@@ -361,19 +370,18 @@ 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') {
-
     $selected_db = $form_state['values']['SELECT_DB'];
     $blastdb_node = node_load($selected_db);
+    $blastdb_name = $blastdb_node->db_name;
     $blastdb_with_path = $blastdb_node->db_path;
-
   }
 
-  // Now let each program process it's own 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)) {
@@ -382,12 +390,38 @@ your sequence headers include pipes (i.e.: | ) they adhere to '
       array($form, &$form_state)
     );
   }
+  else {
+  	$advanced_options = array('none' => 0);
+  }
+
+  // Set path to a BLAST target file to check for its existence
+  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")) {
+      $blastdb_with_suffix = "$blastdb_with_path.nsq";
+    }
+    else if (is_readable("$blastdb_with_path.nal")) {
+      $blastdb_with_suffix = "$blastdb_with_path.nal";
+    }
+  }  
+  else if ($mdb_type == 'prot' && (preg_match('/\.[pn]al/', $blastdb_with_path) == 0)) {
+    // Suffix may be .psq or .pal
+    if (is_readable("$blastdb_with_path.psq")) {
+      $blastdb_with_suffix = "$blastdb_with_path.psq";
+    }
+    else if (is_readable("$blastdb_with_path.pal")) {
+      $blastdb_with_suffix = "$blastdb_with_path.pal";
+    }
+  }
+  else {
+    $blastdb_with_suffix = $blastdb_with_path;
+  }    
 
   // Actually submit the BLAST Tripal Job
-  // NOTE: Tripal jobs needs to be executed from the command-line before it will be run!!
-  $blastdb_with_suffix = $blastdb_with_path . $file_suffix;
   if (is_readable($blastdb_with_suffix)) {
+    // BLAST target exists.
     global $user;
+
     $output_filestub = date('YMd_His');
     $job_args = array(
       'program' => $blast_program,
@@ -396,6 +430,7 @@ your sequence headers include pipes (i.e.: | ) they adhere to '
       'output_filename' => $output_filestub,
       'options' => $advanced_options
     );
+    
     $job_id = tripal_add_job(
       t('BLAST (@program): @query', array('@program' => $blast_program, '@query' => $query)),
       'blast_job',
@@ -403,62 +438,73 @@ your sequence headers include pipes (i.e.: | ) they adhere to '
       $job_args,
       $user->uid
     );
-		//@deepaksomanadh Persist the important data for edit and resubmit
-		$job_data = variable_get('job_data', '');
-		$seq_rows = explode(PHP_EOL, $seq_content);
-		foreach($seq_rows as $row) {
-			if(strpos($row, ">") !== FALSE) {
-				$query_def[] = ltrim($row, ">");
-			}
-		}
-	
-		$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 = base64_encode($job_id);
-		$job_url = "blast/report/$job_encode_id";
-
-		$all_jobs = $_SESSION['all_jobs'];
-		
-		$session_jobs = $all_jobs[$sid];
-		$session_jobs[$job_id] = array(
-															'job_output_url'=> $job_url, 
-															'query_defs' => $query_def,
-															'program' => $blast_program,
-														 );
-		$all_jobs[$sid] = $session_jobs;
-		$_SESSION['all_jobs'] = $all_jobs;
-	
-		tripal_jobs_launch(1, $job_id);
-		//Encode the job_id
-		$job_encode_id = base64_encode($job_id);
+    
+    $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 = base64_encode($job_id);
+    $job_url = "blast/report/$job_encode_id";
+
+    $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 = base64_encode($job_id);
+    
     // Redirect to the BLAST results page
     drupal_goto("blast/report/$job_encode_id");
-  }
-  // We check if $error is set to TRUE because if so then the error has already
-  // been reported.
-  elseif (!$error) {
-    $dbfile_uploaded_msg = ($form_state['dbFlag'] == 'upDB') ? 'The BLAST database was submitted via user upload.' : 'Existing BLAST Database was chosen';
+  }//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. $dbfile_uploaded_msg",
-      array('%db' => $blastdb_with_path)
+      "BLAST database %db unaccessible. %msg",
+      array('%db' => $blastdb_with_path, '%msg' => $dbfile_uploaded_msg)
     );
-    drupal_set_message('BLAST database unaccessible. Please contact the site administrator.','error');
+    $msg = "$dbfile_uploaded_msg BLAST database '$blastdb_with_path' is unaccessible. ";
+    $msg .= "Please contact the site administrator.";
+    drupal_set_message($msg, 'error');
   }
-}
+}//blast_ui_per_blast_program_form_submit

+ 20 - 3
includes/blast_ui.linkouts.inc

@@ -52,6 +52,7 @@
  * human-readable name to be used in the Blast Database add/edit form and the
  * function to be used to determine the URL for each hit in BLAST results.
  */
+
 function blast_ui_blast_linkout_info() {
   $types = array();
 
@@ -75,6 +76,11 @@ function blast_ui_blast_linkout_info() {
     'process function' => 'tripal_blast_generate_linkout_jbrowse',
   );
 
+  $types['custom'] = array(
+    'name' => 'Custom',
+    'process function' => 'tripal_custom_generate_linkout',
+  );
+
   return $types;
 }
 
@@ -143,13 +149,24 @@ function tripal_blast_generate_linkout_gbrowse($url_prefix, $hit, $info, $option
   $ranges = array();
   $coords = array();
   foreach($info['HSPs'] as $hsp) {
-     array_push($ranges,$hsp['Hsp_hit-from'] . '..' . $hsp['Hsp_hit-to'] );
-     array_push($coords,$hsp['Hsp_hit-from'] , $hsp['Hsp_hit-to'] );
+     $start = min($hsp['Hsp_hit-from'], $hsp['Hsp_hit-to']);
+     $stop = max($hsp['Hsp_hit-from'], $hsp['Hsp_hit-to']);
+     array_push($ranges, "$start..$stop");
+     array_push($coords, $start, $stop);
    }
    $min = min($coords);
    $max = max($coords);
    $joined_ranges = join ("," , $ranges);
-   $url_postfix = '&start=' . $min . '&stop='  . $max . '&add=' . $hit->{'hit_name'} . '+BLAST+' . $hit->{'hit_name'} . '_' . $info['query_name'] . '_' . $info['e-value'] . '+' . $joined_ranges ;
+//   $track_name = $hit->{'hit_name'} . '_' . $info['query_name'] . '_' . $info['e-value'];
+   $track_name = $hit->{'linkout_id'} . '_' . $info['query_name'] . '_' . $info['e-value'];
+   
+//   $url_postfix = 'query=';
+   $url_postfix = 'start=' . $min . ';stop=' . $max;
+//   $url_postfix .= ';ref=' . $hit->{'hit_name'};
+//   $url_postfix .= ';add=' . $hit->{'hit_name'} . '+BLAST+Query+' . $joined_ranges;
+   $url_postfix .= ';ref=' . $hit->{'linkout_id'};
+   $url_postfix .= ';add=' . $hit->{'linkout_id'} . '+BLAST+Query+' . $joined_ranges;
+   $url_postfix .= ';h_feat=Query';
 
    return $url_prefix . $url_postfix;
 }

+ 43 - 24
includes/blast_ui.node.inc

@@ -175,7 +175,8 @@ function blastdb_form($node, &$form_state) {
     '#description' => 'The external database you would like to link-out to. '
       . 'Note that this list includes all Tripal Databases and if the database '
       . 'you would like to link-out to is not included you can add it through '
-      . l('Administration > Tripal > Chado Modules > Databases','admin/tripal/chado/tripal_db/add', array('attributes' => array('target' => '_blank'))) . '.',
+      . l('Administration > Tripal > Chado Modules > Databases','admin/tripal/chado/tripal_db/add', array('attributes' => array('target' => '_blank')))
+      . '.',
     '#options' => $db_options,
     '#default_value' => (isset($node->linkout->db_id->db_id)) ? $node->linkout->db_id->db_id : 0
   );
@@ -188,7 +189,14 @@ function blastdb_form($node, &$form_state) {
   $form['dbxref']['dbxref_linkout_type'] = array(
     '#type' => 'select',
     '#title' => 'Link-out Type',
-    '#description' => 'This determines how the URL to be linked to is formed. NOTE: this is very dependant on the External Database chosen above since it needs to be able to support the type of linking choosen. For example, only External Databases which reference a GBrowse instance can use the GBrowse link type.',
+    '#description' => 'This determines how the URL to be linked to is formed. '
+                    . 'NOTE: this is very dependant on the External Database '
+                    . 'chosen above since it needs to be able to support the '
+                    . 'type of linking choosen. For example, only External '
+                    . 'Databases which reference a GBrowse instance can use the '
+                    . 'GBrowse link type.  If a link requires customized code, '
+                    . 'select "custom" and add the code to the file ' 
+                    . 'includes/blast_ui.custom/inc.',
     '#options' => $options,
     '#default_value' => (isset($node->linkout->type)) ? $node->linkout->type : 'link'
   );
@@ -234,7 +242,7 @@ function blastdb_form_validate($form, $form_state) {
  */
 function blastdb_insert($node) {
 
-  // Hangle Link-out Rules.
+  // Handle Link-out Rules.
   if ($node->dbxref_id_type == 'custom') {
     $regex = $node->regex;
   }
@@ -242,17 +250,20 @@ function blastdb_insert($node) {
     $regex = $node->dbxref_id_type;
   }
 
+  if (!$node->dbxref_linkout_type) {
+    $node->dbxref_linkout_type = 'link';
+  }
+  
   // Actually insert the record.
   db_insert('blastdb')->fields(array(
-    'nid' => $node->nid,
-    'name' => $node->db_name,
-    'path' => $node->db_path,
-    'dbtype' => $node->db_dbtype,
-    'dbxref_id_regex' => $regex,
-    'dbxref_db_id' => $node->db_id,
-    'dbxref_linkout_type' => $node->dbxref_linkout_type
+    'nid'                 => $node->nid,
+    'name'                => $node->db_name,
+    'path'                => $node->db_path,
+    'dbtype'              => $node->db_dbtype,
+    'dbxref_id_regex'     => $regex,
+    'dbxref_db_id'        => $node->db_id,
+    'dbxref_linkout_type' => $node->dbxref_linkout_type,
   ))->execute();
-
 }
 
 /**
@@ -270,7 +281,7 @@ function blast_ui_node_insert($node) {
  */
 function blastdb_update($node) {
 
-  // Hangle Link-out Rules.
+  // Handle Link-out Rules.
   if ($node->dbxref_id_type == 'custom') {
     $regex = $node->regex;
   }
@@ -278,23 +289,27 @@ function blastdb_update($node) {
     $regex = $node->dbxref_id_type;
   }
 
-  // Actually insert the record.
+  if (!$node->dbxref_linkout_type) {
+    $node->dbxref_linkout_type = 'link';
+  }
+  
+  // Update the record.
   db_update('blastdb')->fields(array(
-    'name' => $node->db_name,
-    'path' => $node->db_path,
-    'dbtype' => $node->db_dbtype,
-    'dbxref_id_regex' => $regex,
-    'dbxref_db_id' => $node->db_id,
-    'dbxref_linkout_type' => $node->dbxref_linkout_type
+    'name'                => $node->db_name,
+    'path'                => $node->db_path,
+    'dbtype'              => $node->db_dbtype,
+    'dbxref_id_regex'     => $regex,
+    'dbxref_db_id'        => $node->db_id,
+    'dbxref_linkout_type' => $node->dbxref_linkout_type,
   ))->condition('nid', $node->nid)->execute();
 }
 
 /**
  * Implements hook_node_update().
- * This	function acts on ALL NODES
+ * This  function acts on ALL NODES
  */
 function blast_ui_node_update($node) {
-  if ($node->type == 'blastdb')	{
+  if ($node->type == 'blastdb')  {
     $node->title = $node->db_name;
   }
 }
@@ -303,7 +318,7 @@ function blast_ui_node_update($node) {
  * Implements hook_delete().
  */
 function blastdb_delete($node) {
-   db_delete('blastdb')->condition('nid',$node->nid)->execute();
+  db_delete('blastdb')->condition('nid',$node->nid)->execute();
 }
 
 /**
@@ -311,7 +326,12 @@ function blastdb_delete($node) {
  */
 function blastdb_load($nodes) {
 
-  $result = db_query('SELECT nid, name, path, dbtype, dbxref_id_regex, dbxref_db_id, dbxref_linkout_type FROM {blastdb} WHERE nid IN (:nids)', array(':nids' => array_keys($nodes)));
+  $sql = "
+    SELECT nid, name, path, dbtype, dbxref_id_regex, dbxref_db_id, 
+           dbxref_linkout_type
+    FROM {blastdb} 
+    WHERE nid IN (:nids)";
+  $result = db_query($sql, array(':nids' => array_keys($nodes)));
 
   foreach ($result as $record) {
     $nodes[$record->nid]->db_name = $record->name;
@@ -356,7 +376,6 @@ function blastdb_load($nodes) {
       $nodes[$record->nid]->linkout->none = TRUE;
     }
   }
-
 }
 
 /**

+ 192 - 0
includes/blast_ui.services.inc

@@ -0,0 +1,192 @@
+<?php
+function blast_ui_services_resources() {
+  return array(
+    'blast' => array(
+      'retrieve' => array(
+        'help' => 'Retrieves a blast_ui',       
+        'callback' => '_blast_ui_retrieve',
+         'access callback' => 'user_access',
+        'access arguments' => array('access user profiles'),
+        'args' => array(),
+      ),
+      'create' => array(
+        'help' => 'Creates a blast_ui',
+        'callback' => '_blast_ui_create',
+        'access arguments' => array('access content'),
+        'access arguments append' => false,
+        'args' => array(
+           array(
+              'name' => 'param',
+              'type' => 'array',
+              'description' => 'The node information',
+              'source' => 'data',
+              'optional' => FALSE,
+          ),
+        ),
+      ),
+        'update' => array(
+        'help' => 'Updates a blast_ui',
+        'callback' => '_blast_ui_update',
+       'access callback' => 'user_access',
+        'access arguments' => array('access user profiles'),
+        'args' => array(
+          array(
+            'name' => 'id',
+            'type' => 'int',
+            'description' => 'The id of the node to update',
+            'source' => array('path' => '0'),
+            'optional' => FALSE,
+          ),
+          array(
+            'name' => 'data',
+            'type' => 'struct',
+            'description' => 'The node data object',
+            'source' => 'data',
+            'optional' => FALSE,
+          ),
+        ),
+      ),
+      'delete' => array(
+        'help' => 'Deletes a blast_ui',
+        'callback' => '_blast_ui_delete',
+         'access callback' => 'user_access',
+       'access arguments' => array('access content'),
+        'access arguments append' => TRUE,
+        'args' => array(
+          array(
+            'name' => 'nid',
+            'type' => 'int',
+            'description' => 'The id of the note to delete',
+            'source' => array('path' => '0'),
+            'optional' => FALSE,
+          ),
+        ),
+      ),
+      'index' => array(
+        'help' => 'Retrieves a listing of blast_ui',
+        'callback' => '_blast_ui_index',
+        'access callback' => 'user_access',
+        'access arguments' => array('access content'),
+        'access arguments append' => FALSE,
+        'args' => array(),
+        ),
+     
+       'actions' => array(
+    	'getDatabaseType' => array(
+    	'help' => 'Retrieves a listing of database',
+        'callback' => '_blast_ui_getDatabaseType',
+        'access callback' => 'user_access',
+        'access arguments' => array('access content'),
+        'access arguments append' => FALSE,
+        'args' => array(),
+         ),
+         'getDatabaseOptions' => array(
+    	'help' => 'Retrieves a listing of database',
+        'callback' => '_blast_ui_getDatabaseOption',
+        'access callback' => 'user_access',
+        'access arguments' => array('access content'),
+        'access arguments append' => FALSE,
+        'args' => array(),
+         ),
+        ),
+       ),
+   );
+    
+}
+
+
+
+
+
+function _blast_ui_create($param) {
+  
+ return services_error('Missing _blast_ui_create', 406);
+}
+
+
+/**
+* Callback for updating note services.
+*
+* @param int $id
+* @param object $data
+* @return object
+*/
+function _blast_ui_update($id, $data) {
+  return services_error('Missing _blast_ui_update', 406);
+} 
+/**
+* Callback for retrieving note services.
+*
+* @param int $id
+* @return object
+*/
+function _blast_ui_retrieve($id) {
+ return services_error('Missing _blast_ui_retrieve', 406);
+}
+
+/**
+* Callback for deleting note services.
+*
+* @param int $id
+* @return object
+*/
+function _blast_ui_delete($id) {
+  return services_error('Missing _blast_ui_delete', 406);
+}
+
+function _blast_ui_index($page, $parameters) {
+ return array(
+      'Nucleotide' => array ( 
+        'Nucleotide' => 'blastn',
+      	'protein' => 'blastx',
+      ),
+      'Protein' => array ( 
+        'Nucleotide' => 'tblastn',
+      	'protein' => 'blastp',
+      ),
+    ); 
+  
+//  return services_error('Missing _blast_ui_index solved', 406);
+}
+
+function _blast_ui_getDatabaseType() {
+
+    return array(
+      'Nucleotide' => array ( 
+        'Nucleotide' => 'blastn',
+      	'protein' => 'blastx',
+      ),
+      'Protein' => array ( 
+        'Nucleotide' => 'tblastn',
+      	'protein' => 'blastp',
+      ),
+    ); 
+}
+
+
+function _blast_ui_getDatabaseOption() {
+
+ $db_type = 'nucleotide';
+ $options = get_blast_database_options($db_type);
+return $options;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 56 - 71
theme/blast_align_image.php

@@ -17,22 +17,10 @@
  * history:
  *    09/23/10  Carson  created
  *    04/16/12  eksc    adapted into POPcorn code
- *		03/12/15	deepak	Adapted code into Tripal BLAST
+ *    03/12/15  deepak  Adapted code into Tripal BLAST
  */
  
-  /* include_once('../../inc/lib.php');
-   session_start();
-   $pc_system = getSystemInfoPC('sequence_search');
-  
-   $acc    = getCGIParamPC('acc',    'GP', '');
-   $scores = getCGIParamPC('scores', 'GP', '');
-   $links  = getCGIParamPC('links',  'GP', '');
-   $hits   = getCGIParamPC('hits',   'GP', '');
-   $tsize  = intval(getCGIParamPC('tsize', 'GP', ''));
-   $qsize  = intval(getCGIParamPC('qsize', 'GP', ''));
-   $name  = getCGIParamPC('name',    'GP', '');
-  */
-   // extract hit information from hit param
+// extract hit information from hit param
 function generateImage($acc = '', $scores, $hits, $tsize, $qsize, $name, $hit_name) {
    $tok = strtok($hits, ";");
    $b_hits = Array();
@@ -118,77 +106,77 @@ function generateImage($acc = '', $scores, $hits, $tsize, $qsize, $name, $hit_na
    // 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;
+  
+     $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
+     // 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;
+     // 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,);
+       
+     $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);
+     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);
+     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);
+     $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
 
@@ -215,9 +203,6 @@ function generateImage($acc = '', $scores, $hits, $tsize, $qsize, $name, $hit_na
    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;
-  // write out images
-//    header("Content-type: image/png");
-//    imagepng($img);
+   return $img;
 }
-?>
+?>

+ 5 - 5
theme/blast_nucleotide_user_menupage.tpl.php

@@ -35,25 +35,25 @@ local alignment search tool. J. Mol. Biol., 215, 403–410.</blockquote>
     <th>BLAST Program</th>
   </tr>
   <tr class= "blast-highlighted">
-    <td rowspan="2">Nucleotide</td>
     <td>Nucleotide</td>
-    <td><?php print l('blastn', 'blast/nucleotide/nucleotide');?>:
+    <td rowspan="2">Nucleotide</td>
+    <td><?php print l('blastn', './blast/nucleotide/nucleotide');?>:
       Search a nucleotide database using a nucleotide query.</td>
   </tr>
   <tr class="blast-highlighted">
     <td>Protein</td>
-    <td><?php print l('blastx', 'blast/nucleotide/protein');?>:
+    <td><?php print l('blastx', './blast/nucleotide/protein');?>:
       Search protein database using a translated nucleotide query.</td>
   </tr>
   <tr>
     <td  rowspan="2">Protein</td>
     <td>Nucleotide</td>
-    <td><?php print l('tblastn', 'blast/protein/nucleotide');?>:
+    <td><?php print l('tblastn', './blast/protein/nucleotide');?>:
       Search translated nucleotide database using a protein query.</td>
   </tr>
   <tr>
     <td>Protein</td>
-    <td><?php print l('blastp', 'blast/protein/protein');?>:
+    <td><?php print l('blastp', './blast/protein/protein');?>:
       Search protein database using a protein query.</td>
   </tr>
 </table>

+ 4 - 5
theme/blast_protein_user_menupage.tpl.php

@@ -4,7 +4,6 @@
  * @file
  *
  */
-
 ?>
 
 <style>
@@ -37,23 +36,23 @@ local alignment search tool. J. Mol. Biol., 215, 403–410.</blockquote>
   <tr>
     <td rowspan="2">Nucleotide</td>
     <td>Nucleotide</td>
-    <td><?php print l('blastn', 'blast/nucleotide/nucleotide');?>:
+    <td><?php print l('blastn', './blast/nucleotide/nucleotide');?>:
       Search a nucleotide database using a nucleotide query.</td>
   </tr>
   <tr>
     <td>Protein</td>
-    <td><?php print l('blastx', 'blast/nucleotide/protein');?>:
+    <td><?php print l('blastx', './blast/nucleotide/protein');?>:
       Search protein database using a translated nucleotide query.</td>
   </tr>
   <tr class="blast-highlighted">
     <td  rowspan="2">Protein</td>
     <td>Nucleotide</td>
-    <td><?php print l('tblastn', 'blast/protein/nucleotide');?>:
+    <td><?php print l('tblastn', './blast/protein/nucleotide');?>:
       Search translated nucleotide database using a protein query.</td>
   </tr>
   <tr class="blast-highlighted">
     <td>Protein</td>
-    <td><?php print l('blastp', 'blast/protein/protein');?>:
+    <td><?php print l('blastp', './blast/protein/protein');?>:
       Search protein database using a protein query.</td>
   </tr>
 </table>

+ 192 - 159
theme/blast_report.tpl.php

@@ -5,28 +5,29 @@
  *
  * 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
+ *    @deepaksomanadh: $job_data = meta data related to the current job
  */
+ 
+// uncomment this to see the contents of the $blastdb object
+//echo "blastdb:<pre>";var_dump($blastdb);echo "</pre>";
 
 // Set ourselves up to do link-out if our blast database is configured to do so.
 $linkout = FALSE;
+
 if ($blastdb->linkout->none === FALSE) {
-  $linkout = TRUE;
+  $linkout_type  = $blastdb->linkout->type;
   $linkout_regex = $blastdb->linkout->regex;
-  if (isset($blastdb->linkout->db_id->urlprefix) AND !empty($blastdb->linkout->db_id->urlprefix)) {
+  
+  // 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;
-
-    // Furthermore, check that we can determine the URL.
-    // (ie: that the function specified to do so, exists).
-    if (function_exists($blastdb->linkout->url_function)) {
-      $url_function = $blastdb->linkout->url_function;
-    }
-    else {
-      $linkout = FALSE;
-    }
   }
-  else {
-    $linkout = FALSE;
+
+  // 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;
+    $linkout = TRUE;
   }
 }
 
@@ -40,8 +41,15 @@ $no_hits = TRUE;
 
 ?>
 
-<!-- JQuery controlling display of the alignment information (hidden by default) -->
 <script type="text/javascript">
+  window.onload = function() {
+    if (!window.location.hash) {
+      window.location = window.location + '#loaded';
+      window.location.reload();
+    }
+  }
+
+  // JQuery controlling display of the alignment information (hidden by default)
   $(document).ready(function(){
 
     // Hide the alignment rows in the table
@@ -67,49 +75,46 @@ $no_hits = TRUE;
 </style>
 
 <p><strong>Download</strong>:
-  <a href="<?php print '../../' . $html_filename; ?>">HTML</a>,
+  <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 -->
+
+<!--  @deepaksomanadh: For displaying BLAST command details -->
 <table>
 <tr>
-	<th>Input query sequence(s) </th>
-	<th>Target Database selected </th>
-	<th>BLAST command executed </th>
+  <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>"
- ?> 
-
-
-<?php
-	include_once("blast_align_image.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>";	
+  //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 open a new window with a genome browser around this hit.</p>
+and click the <strong>target name </strong> to get more information about the target hit.</p>
 
 <?php
 include_once("blast_align_image.php");
@@ -124,7 +129,7 @@ $xml = simplexml_load_file($xml_filename);
 if ($xml) {
   // Specify the header of the table
   $header = array(
-		'arrow-col' =>  array('data' => '', 'class' => array('arrow-col')),
+    'arrow-col' =>  array('data' => '', 'class' => array('arrow-col')),
     'number' =>  array('data' => '#', 'class' => array('number')),
     'query' =>  array('data' => 'Query Name  (Click for alignment & visualization)', 'class' => array('query')),
     'hit' =>  array('data' => 'Target Name', 'class' => array('hit')),
@@ -137,110 +142,150 @@ if ($xml) {
   // Parse the BLAST XML to generate the rows of the table
   // where each hit results in two rows in the table: 1) A summary of the query/hit and
   // significance and 2) additional information including the alignment
-  foreach($xml->{'BlastOutput_iterations'}->children() as $iteration) {
+  foreach ($xml->{'BlastOutput_iterations'}->children() as $iteration) {
     $children_count = $iteration->{'Iteration_hits'}->children()->count();
-		//@deepaksomanadh: Code added for BLAST visualization
-		// parameters that need to be passed for BLAST image generation
-		$target_name = '';
-		$q_name = $xml->{'BlastOutput_query-def'};
-		$query_size = $xml->{'BlastOutput_query-len'};
-		$target_size = $iteration->{'Iteration_stat'}->{'Statistics'}->{'Statistics_db-len'};
-		
-    if($children_count != 0) {
-      foreach($iteration->{'Iteration_hits'}->children() as $hit) {
+    //@deepaksomanadh: Code added for BLAST visualization
+    // parameters that need to be passed for BLAST image generation
+    $target_name = '';
+    $q_name = $xml->{'BlastOutput_query-def'};
+    $query_size = $xml->{'BlastOutput_query-len'};
+    $target_size = $iteration->{'Iteration_stat'}->{'Statistics'}->{'Statistics_db-len'};
+    
+    if ($children_count != 0) {
+      foreach ($iteration->{'Iteration_hits'}->children() as $hit) {
         if (is_object($hit)) {
           $count +=1;
           $zebra_class = ($count % 2 == 0) ? 'even' : 'odd';
           $no_hits = FALSE;
 
-					// RETRIEVE INFO
-          $hit_name = (preg_match('/BL_ORD_ID/', $hit->{'Hit_id'})) ? $hit->{'Hit_def'} : $hit->{'Hit_id'};	
-					$score = $hit->{'Hit_hsps'}->{'Hsp'}->{'Hsp_score'};
-					$evalue = $hit->{'Hit_hsps'}->{'Hsp'}->{'Hsp_evalue'};
-				  $query_name = $iteration->{'Iteration_query-def'};
-
-					// Round e-val to two decimal values
-					$rounded_evalue = '';
-					if (strpos($evalue,'e') != false) {
-					 $evalue_split = explode('e', $evalue);
-					 $rounded_evalue = round($evalue_split[0], 2, PHP_ROUND_HALF_EVEN);				    
-						 $rounded_evalue .= 'e' . $evalue_split[1];
-					}
-					else { 
-							$rounded_evalue = $evalue;
-					}				
-				
-				  // ALIGNMENT ROW (collapsed by default)
-					// Process HSPs
-					// @deepaksomanadh: Code added for BLAST visualization
-					// hit array and corresponding bit scores 
-					// hits=4263001_4262263_1_742;4260037_4259524_895_1411;&scores=722;473;
-					$HSPs = array();
-					$hit_hsps = '';
-					$hit_hsp_score = '';
-					$target_size = $hit->{'Hit_len'};
-		
-					foreach ($hit->{'Hit_hsps'}->children() as $hsp_xml) {
-						$HSPs[] = (array) $hsp_xml;
-		
-						$hit_hsps .=  $hsp_xml->{'Hsp_hit-from'} . '_' . $hsp_xml->{'Hsp_hit-to'}  
-														. '_' . $hsp_xml->{'Hsp_query-from'} . '_'
-														. $hsp_xml->{'Hsp_query-to'} . ';';	
-						$Hsp_bit_score .= 	$hsp_xml->{'Hsp_bit-score'} .';';							
-
-					}	 
-					// SUMMARY ROW
-					// If the id is of the form gnl|BL_ORD_ID|### then the parseids flag
-					// to makeblastdb did a really poor job. In this case we want to use
-					// the def to provide the original FASTA header.
-					
+          // RETRIEVE INFO
+          $hit_name = (preg_match('/BL_ORD_ID/', $hit->{'Hit_id'})) ? $hit->{'Hit_def'} : $hit->{'Hit_id'};  
+          $score = $hit->{'Hit_hsps'}->{'Hsp'}->{'Hsp_score'};
+          $evalue = $hit->{'Hit_hsps'}->{'Hsp'}->{'Hsp_evalue'};
+          $query_name = $iteration->{'Iteration_query-def'};
+
+          // Round e-val to two decimal values
+          $rounded_evalue = '';
+          if (strpos($evalue,'e') != false) {
+            $evalue_split = explode('e', $evalue);
+            $rounded_evalue = round($evalue_split[0], 2, PHP_ROUND_HALF_EVEN);            
+            $rounded_evalue .= 'e' . $evalue_split[1];
+          }
+          else { 
+            $rounded_evalue = $evalue;
+          }        
+        
+          // ALIGNMENT ROW (collapsed by default)
+          // Process HSPs
+          // @deepaksomanadh: Code added for BLAST visualization
+          // hit array and corresponding bit scores 
+          // hits=4263001_4262263_1_742;4260037_4259524_895_1411;&scores=722;473;
+          $HSPs = array();
+          $track_start = INF;
+          $track_end = -1;
+          $hsps_range = '';
+          $hit_hsps = '';
+          $hit_hsp_score = '';
+          $target_size = $hit->{'Hit_len'};
+    
+          foreach ($hit->{'Hit_hsps'}->children() as $hsp_xml) {
+            $HSPs[] = (array) $hsp_xml;
+    
+            if ($track_start > $hsp_xml->{'Hsp_hit-from'}) {
+              $track_start = $hsp_xml->{'Hsp_hit-from'} . "";
+            }
+            if ($track_end < $hsp_xml->{'Hsp_hit-to'}) {
+              $track_end = $hsp_xml->{'Hsp_hit-to'} . "";
+            }
+          }  
+          $range_start = (int) $track_start - 50000;
+          $range_end = (int) $track_end + 50000;
+        
+          if ($range_start < 1) 
+            $range_start = 1;  
+
+          // For BLAST visualization 
+          $target_size = $hit->{'Hit_len'};
+        
+          foreach ($hit->{'Hit_hsps'}->children() as $hsp_xml) {
+            $hit_hsps .=  $hsp_xml->{'Hsp_hit-from'} . '_' . 
+                          $hsp_xml->{'Hsp_hit-to'} . '_' . 
+                          $hsp_xml->{'Hsp_query-from'} . '_' . $hsp_xml->{'Hsp_query-to'} . 
+                          ';';  
+            $Hsp_bit_score .=   $hsp_xml->{'Hsp_bit-score'} .';';              
+          }      
+          
+          // SUMMARY ROW
+          // If the id is of the form gnl|BL_ORD_ID|### then the parseids flag
+          // to makeblastdb did a really poor job. In this case we want to use
+          // the def to provide the original FASTA header.
+          
           // 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'};
+          $query_name = $iteration->{'Iteration_query-def'};
+ 
           if ($linkout) {
+//echo "link out regex: $linkout_regex executed on [$hit_name]<br>";
+//preg_match($linkout_regex, $hit_name, $linkout_match);
+//echo "<br>matches:<pre>" . var_dump($linkout_match);echo "</pre>";
             if (preg_match($linkout_regex, $hit_name, $linkout_match)) {
-
               $linkout_id = $linkout_match[1];
               $hit->{'linkout_id'} = $linkout_id;
               $hit->{'hit_name'} = $hit_name;
-
-              $hit_url = call_user_func(
-                $url_function,
-                $linkout_urlprefix,
-                $hit,
-                array(
-                  'query_name' => $query_name,
-                  'score' => $score,
-                  'e-value' => $evalue,
-                  'HSPs' => $HSPs
-                )
-              );
-
-              if ($hit_url) {
-                $hit_name = l(
-                  $linkout_id,
-                  $hit_url,
-                  array('attributes' => array('target' => '_blank'))
-                );
-              }
             }
-          }
+            
+            $hit_url = call_user_func(
+              $url_function,
+              $linkout_urlprefix,
+              $hit,
+              array(
+                'query_name' => $query_name,
+                'score'      => $score,
+                'e-value'    => $evalue,
+                'HSPs'       => $HSPs,
+                'Target'     => $blastdb->title,
+              )
+            );
+            
+            // The linkout id might have been set/changed by the custom linkout code.
+            if ($linkout_type == 'custom' && $hit->{'linkout_id'}) {
+              $linkout_id = $hit->{'linkout_id'};
+            }
+
 
-					//@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.'"/>';
-					
+            if ($hit_url) {
+/* eksc- l() URL-encodes the URL path too, which is often not what we want.
+                  $hit_name = l(
+                    $linkout_id,
+                    $hit_url,
+                    array('attributes' => array('target' => '_blank'))
+                  );
+*/
+               $hit_name = "
+                  <a href=\"$hit_url\" target=\"_blank\">
+                    $linkout_id
+                  </a>";
+            }
+          }//handle linkout
+
+          //@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.'"/>';
+          
           $row = array(
             'data' => array(
-							'arrow-col' => array('data' => '<div class="arrow"></div>', 'class' => array('arrow-col')),
+              'arrow-col' => array('data' => '<div class="arrow"></div>', 'class' => array('arrow-col')),
               'number' => array('data' => $count, 'class' => array('number')),
               'query' => array('data' => $query_name, 'class' => array('query')),
               'hit' => array('data' => $hit_name, 'class' => array('hit')),
@@ -256,13 +301,13 @@ if ($xml) {
 
           $row = array(
             'data' => array(
-							'arrow' => '',
+              'arrow' => '',
               'number' => '',
               'query' => array(
                 'data' => theme('blast_report_alignment_row', array('HSPs' => $HSPs)),
               //  'colspan' => 4,
               ),
-							'hit' => array(
+              'hit' => array(
                 'data' => $hit_img,
                 'colspan' => 3,
               ),
@@ -272,17 +317,17 @@ if ($xml) {
           );
           $rows[] = $row;
 
-        }// end of if - checks $hit
-      } //end of foreach - iteration_hits
-    }	// end of if - check for iteration_hits
+        }//end of if - checks $hit
+      }//end of foreach - iteration_hits
+    }//end of if - check for iteration_hits
+    
     else {
-
       // Currently where the "no results" is added.
       $query_name = $iteration->{'Iteration_query-def'};
       $query_with_no_hits[] = $query_name;
 
-		} // end of else
-  }	//end of foreach - BlastOutput_iterations
+    }//no results
+  }//end of foreach - BlastOutput_iterations
 
   if ($no_hits) {
     print '<p class="no-hits-message">No results found.</p>';
@@ -303,28 +348,16 @@ if ($xml) {
         'attributes' => array('id' => 'blast_report'),
       ));
     }
-  }
-}
+  }//handle no hits
+}//XML exists
+
 else {
   drupal_set_title('BLAST: Error Encountered');
   print '<p>We encountered an error and are unable to load your BLAST results.</p>';
 }
 ?>
-<p> <!--	@deepaksomanadh: Building the edit and resubmit URL --> 
-	 <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> 
+  <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>
-<strong> Recent Jobs </strong>
-	<ol>
-	<?php
-			$sid = session_id();	
-			$jobs = $_SESSION['all_jobs'][$sid];
-	
-			foreach ( $jobs as $job) {
-				echo "<li>";
-				$q_def = !isset($job['query_defs'][0]) ? "Query" : $job['query_defs'][0];
-				echo "<a href='" . "../../" . $job['job_output_url'] ."' >"  
-								. $q_def ."->". $job['program'] . "</a>";
-				echo "</li>";
-			}
-	?>
-	</ol>
+<?php echo get_recent_jobs(); ?>

+ 30 - 28
theme/blast_report_alignment_row.tpl.php

@@ -47,32 +47,34 @@
         // 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'];
-			
-					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'];
-					}
-					// 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]);
-	        }
+        
+        // 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'];
+          
+          }
+          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">
@@ -82,12 +84,12 @@
             <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;', 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;&nbsp;&nbsp;
+            <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>

+ 8 - 7
theme/blast_ui.theme.inc

@@ -24,17 +24,18 @@ 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);
-  $vars['xml_filename'] = variable_get('file_public_path', conf_path() . '/files') . '/' . $job_args['output_filename'] . '.blast.xml';
-  $vars['tsv_filename'] = variable_get('file_public_path', conf_path() . '/files') . '/' . $job_args['output_filename'] . '.blast.tsv';
-  $vars['html_filename'] = variable_get('file_public_path', conf_path() . '/files') . '/' . $job_args['output_filename'] . '.blast.html';
+//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']));
-	//@deepaksomanadh: code added to use the persisted data in the template file.
-	$job_id = $vars['job_id'];
-	$job_data = variable_get('job_data', '');
-	$vars['job_id_data'] = $job_data[$job_id];
+  //@deepaksomanadh: code added to use the persisted data in the template file.
+  $job_id = $vars['job_id'];
+  $job_data = variable_get('job_data', '');
+  $vars['job_id_data'] = $job_data[$job_id];
 }
 
 /**

+ 16 - 18
theme/blast_user_menupage.tpl.php

@@ -7,20 +7,16 @@
 
 ?>
 
-<p>In bioinformatics, BLAST (Basic Local Alignment Search Tool) is an algorithm
-for comparing primary biological sequence information, such as the amino-acid
-sequences of different proteins or the nucleotides of DNA sequences. A BLAST
-search enables a researcher to compare a query sequence with a library or
-database of sequences, and identify library sequences that resemble the query
-sequence above a certain threshold. Different types of BLASTs are available
-according to the query sequences. For example, following the discovery of a
-previously unknown gene in the mouse, a scientist will typically perform a
-BLAST search of the human genome to see if humans carry a similar gene;
-BLAST will identify sequences in the human genome that resemble the mouse
-gene based on similarity of sequence.</p>
-
-<blockquote>Altschul,S.F., Gish,W., Miller,W., Myers,E.W. and Lipman,D.J. (1990) Basic
-local alignment search tool. J. Mol. Biol., 215, 403–410.</blockquote>
+<h1> BLAST Search </h1>
+<p>
+  Search for one or more of your sequences (using BLAST). First pick 
+  a query type (nucleotide or protein). You will be able to set search 
+  parameters on the next page.
+</p>
+<p>
+  Choose the appropriate program based on the Query type and Target
+  database type. Please click on the program name to view the search form.
+<p>
 
 <table>
   <tr>
@@ -31,23 +27,25 @@ local alignment search tool. J. Mol. Biol., 215, 403–410.</blockquote>
   <tr>
     <td  rowspan="2">Nucleotide</td>
     <td>Nucleotide</td>
-    <td><?php print l('blastn', 'blast/nucleotide/nucleotide');?>:
+    <td><?php print l('blastn', './blast/nucleotide/nucleotide');?>:
       Search a nucleotide database using a nucleotide query.</td>
   </tr>
   <tr>
     <td>Protein</td>
-    <td><?php print l('blastx', 'blast/nucleotide/protein');?>:
+    <td><?php print l('blastx', './blast/nucleotide/protein');?>:
       Search protein database using a translated nucleotide query.</td>
   </tr>
   <tr>
     <td  rowspan="2">Protein</td>
     <td>Nucleotide</td>
-    <td><?php print l('tblastn', 'blast/protein/nucleotide');?>:
+    <td><?php print l('tblastn', './blast/protein/nucleotide');?>:
       Search translated nucleotide database using a protein query.</td>
   </tr>
   <tr>
     <td>Protein</td>
-    <td><?php print l('blastp', 'blast/protein/protein');?>:
+    <td><?php print l('blastp', './blast/protein/protein');?>:
       Search protein database using a protein query.</td>
   </tr>
 </table>
+
+<?php echo get_recent_jobs(); ?>

+ 5 - 0
theme/node--blastdb.tpl.php

@@ -97,7 +97,12 @@
 
     <table>
       <tr><th>Human-Readable Name</th><td><?php print $node->db_name; ?></td></tr>
+      <tr><th>Database Path</th><td><?php print $node->db_path; ?></td></tr>
       <tr><th>Database Type</th><td><?php print $node->db_dbtype; ?></td></tr>
+      <tr><th>FASTA Header Format</th><td><?php print $node->linkout->regex_type; ?></td></tr>
+      <tr><th>External Database</th><td><?php print $node->linkout->db_id->name; ?></td></tr>
+      <tr><th>RegEx</th><td><?php print $node->linkout->regex; ?></td></tr>
+      <tr><th>Link-out Type</th><td><?php print $node->linkout->type; ?></td></tr>
     </table>
 
     <?php