Explorar o código

Cleaned up documentation for upcomming collaboration :)

Lacey Sanderson %!s(int64=10) %!d(string=hai) anos
pai
achega
ffe0f661a9

+ 23 - 13
blast_ui.install

@@ -2,21 +2,31 @@
 
 /**
  * @file
- * Contains hooks to handle installation of this module
+ * Contains hooks to handle installation of this module.
+ *
+ * Specifically, a database table (blastdb) is created to store additional information
+ * related to blast database nodes such as the name/path to the NCBI BLAST database files
+ * and the type (protein or nucleotide) of the database.
  */
 
 
 /**
-*
-* Implement hook_install()
-*
-*/
+ * Implements hook_install().
+ */
 function blast_ui_install() {
    tripal_create_files_dir('tripal_blast');
 }
 
+/**
+ * Implements hook_schema().
+ * Create the blastdb database table for storing addditional info related to blastdb nodes.
+ *
+ * NOTE: This hook is called via Drupal magic during the installation process and no longer
+ * needs to be called explicitly in hook_install().
+ */
 function blast_ui_schema(){
-    $schema['blastdb'] = array(
+
+  $schema['blastdb'] = array(
     'description' => t('The base table for blastdb node'),
     'fields' => array(
      'nid' => array(
@@ -24,21 +34,21 @@ function blast_ui_schema(){
       'type' => 'serial',
       'unsigned' => true,
       'not null' => true,
-      ), 
+      ),
      'name' => array(
-       'description' => t('The name of the blast database'),
+       'description' => t('The human-readable name of the blast database.'),
        'type' => 'varchar',
        'length' => 255,
        'not null' => true,
       ),
       'path' => array(
-        'description' => t('The address of the blast database'),
+        'description' => t('The full path and filename prefix of the blast database.'),
         'type' => 'varchar',
          'length' => 1023,
         'not null' => true,
       ),
       'dbtype' => array(
-        'description' => t('Type of the blast database'),
+        'description' => t('Type of the blast database. Should be either n for nucleotide or p for protein.'),
         'type' => 'varchar',
         'length' => 8,
         'not null' => true,
@@ -51,8 +61,8 @@ function blast_ui_schema(){
     'unique keys' => array(
        'nid' => array('nid'),
     ),
-    );
+  );
+
+  return $schema;
 
-    return $schema;
-    
 }

+ 65 - 52
blast_ui.module

@@ -2,46 +2,25 @@
 
 /**
  * @file
- * Contains all functions for the blast module
+ * The main file for the blast UI module.
  */
 
+// Type-specific BLAST functionality
 require_once 'includes/blast_ui.blastn.inc';
 require_once 'includes/blast_ui.blastp.inc';
-require_once 'includes/blast_ui.node.inc';
-require_once 'theme/blast_ui.theme.inc';
-
-/**
- *
- * Implements hook_theme()
- *
- */
-
-function blast_ui_theme() {
-  $items = array();
-
-  $path = drupal_get_path('module', 'blast_ui');
 
-  $items['show_blast_report'] = array(
-    'template' => 'blast_report',
-    'path' => "$path/theme",
-  );
-
-  $items['blast_report_alignment_row'] = array(
-    'template' => 'blast_report_alignment_row',
-    'variables' => array('hsps' => NULL),
-    'path' => "$path/theme",
-  );
+// BLAST DB Node functionality
+require_once 'includes/blast_ui.node.inc';
 
-  return $items;
-}
+// Functions specific to themeing (ie: preprocess)
+require_once 'theme/blast_ui.theme.inc';
 
 /**
- *
- * Implements hook_menu()
- *
+ * Implements hook_menu().
  */
 function blast_ui_menu() {
 
+  // Parent menu-item for BLAST submission
   $items['blast'] = array(
     'title' => 'BLAST',
     'page callback' => 'drupal_get_form',
@@ -49,31 +28,58 @@ function blast_ui_menu() {
     'access arguments' => array('access content'),
     'type' => MENU_NORMAL_ITEM,
     'expanded' => TRUE,
-);
+  );
 
+  // Nucleotide BLAST submission form
+  $items['blast/blastn'] = array(
+    'title' => 'Nucleotide BLAST',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('blast_nucleotide_form'),
+    'access arguments' => array('access content'),
+    'type' => MENU_NORMAL_ITEM
+  );
+
+  // Protein  BLAST submission form
+  $items['blast/blastp'] = array(
+    'title' => 'Protein BLAST',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('blast_protein_form'),
+    'access arguments' => array('access content'),
+    'type' => MENU_NORMAL_ITEM
+  );
+
+  // BLAST Results page
   $items['blast/report/%'] = array(
     'title' => 'BLAST result:',
     'page callback' => 'show_blast_output',
     'page arguments' => array(2),
     'access arguments' => array('access content'),
     'type' => MENU_CALLBACK,
-);
+  );
 
-  $items['blast/blastn'] = array(
-    'title' => 'Nucleotide BLAST',
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('blast_nucleotide_form'),
-    'access arguments' => array('access content'),
-    'type' => MENU_NORMAL_ITEM
+  return $items;
+}
+
+/**
+ * Implements hook_theme().
+ */
+function blast_ui_theme() {
+
+  $items = array();
+  $path = drupal_get_path('module', 'blast_ui');
+
+  // Displays the BLAST results for each job
+  $items['show_blast_report'] = array(
+    'template' => 'blast_report',
+    'path' => "$path/theme",
   );
 
-$items['blast/blastp'] = array(
-   'title' => 'Protein BLAST',
-   'page callback' => 'drupal_get_form',
-   'page arguments' => array('blast_protein_form'),
-   'access arguments' => array('access content'),
-   'type' => MENU_NORMAL_ITEM
-);
+  // Themes the alignments in a BLAST result display
+  $items['blast_report_alignment_row'] = array(
+    'template' => 'blast_report_alignment_row',
+    'variables' => array('hsps' => NULL),
+    'path' => "$path/theme",
+  );
 
   return $items;
 }
@@ -85,23 +91,28 @@ $items['blast/blastp'] = array(
  *  A string containing name of the blast output file.
  *
  * @return $result
- *  Return a string containing the blast search output. A link is also provided to let users download the output file.
+ *  Return HTML output of the BLAST results to be displayed to the user
  *
  */
 function show_blast_output($args = 'all') {
 
-  if (preg_match('/^[^\/]*/',$args)) {
-    // Since the blast results are in the files directory we can use public:// to get around hard-coding the full path
+  // Double-check that there are no directory slashes in the path since this could be used
+  // present a security risk (ie: if the path contained ../../../etc/someconfig.file this
+  // we don't want to process or display anything.
+  if (preg_match('/^[^\/]*$/',$args)) {
+
+    // Since the blast results are in the files directory
+    // we can use public:// to get around hard-coding the full path
     $full_path_filename = 'public://'.$args;
 
+    // check that the XML file exists before trying to display results
     if (file_exists($full_path_filename)) {
-    //  $result = t('<br /><h3>BLAST Results: <a href="@url" target="_blank">HTML</a></h3>', array('@url' => url('sites/default/files/' . $args)));
-    //  $result .= check_markup(file_get_contents($full_path_filename), 'full_html');
-    //  $result = str_replace('<script src="blastResult.js"></script>','',$result);
-
-	$result = theme('show_blast_report');
+      // Use the show_blast_output.tpl.php to generate the HTML
+	    $result = theme('show_blast_report');
     }
     else {
+      // If the file doesn't exist then throw a tripal error
+      // as well as displaying an error to the user
       tripal_report_error(
         'blast_ui',
         TRIPAL_ERROR,
@@ -112,6 +123,8 @@ function show_blast_output($args = 'all') {
     }
   }
   else {
+    // If there are directory slashes in the path then just display an error to the user
+    // rather than risk the security of the server
     $result = '<p>An error was encountered while trying to process your blast results</p>';
   }
 

+ 255 - 226
includes/blast_ui.blastn.inc

@@ -2,254 +2,270 @@
 
 /**
  * @file
- * Contains all functions for the nucleotide blast module 
+ * Contains all functions for the Nucleotide BLAST
  */
 
 
 /**
- * Form constructor for the nucleotide blast form.
+ * Nucleotide BLAST Submission Form
  *
  * @see blast_nucleotide_form_validate()
  * @see blast_nucleotide_form_submit()
- *
  */
 function blast_nucleotide_form($form, &$form_state) {
-  
-//Nucleotide BLAST
 
-$form['nBLAST'] = array(
+
+  // NUCLEOTIDE QUERY
+  //.........................
+
+  $form['query'] = array(
     '#type' => 'fieldset',
     '#title' => t('Enter Query Sequence'),
     '#description' => t('Enter one or more queries in the top text box or use the browse button to upload a file from your local disk. The file may contain a single sequence or a list of sequences. In both cases, the data must be in FASTA format. <a href="http://www.ncbi.nlm.nih.gov/BLAST/blastcgihelp.shtml" target="_blank">More information..</a> '),
-    '#collapsible' => TRUE, 
-    '#collapsed' => FALSE,  
+    '#collapsible' => TRUE,
+    '#collapsed' => FALSE,
   );
-$form['nBLAST']['FASTA'] = array(
+
+  // Textfield for submitting a mult-FASTA query
+  $form['query']['FASTA'] = array(
     '#type' => 'textarea',
     '#title' => t('Enter FASTA sequence(s)'),
     '#description'=>t('Enter query sequence(s) in the text area.'),
   );
 
-// Upload a file as an alternative to enter a query sequence 
-$form['#attributes']['enctype'] = 'multipart/form-data';
-$form['nBLAST']['UPLOAD'] = array(
-  	'#prefix' => 'Or upload your query files:	',
-  	'#type' => 'file',
-  	'#description' => t('The file should be a plain-text FASTA file and not a .doc, .docx, etc. It cannot be greater than 10 Mb in size.'),
+  // Upload a file as an alternative to enter a query sequence
+  $form['#attributes']['enctype'] = 'multipart/form-data';
+  $form['query']['UPLOAD'] = array(
+    '#prefix' => 'Or upload your query files:	',
+    '#type' => 'file',
+    '#description' => t('The file should be a plain-text FASTA file and not a .doc, .docx, etc. It cannot be greater than 10 Mb in size.'),
   );
 
 
-//DATABASE//
-
-$form['DB'] = array(
-  '#type' => 'fieldset',
-  '#title' => t('Choose Search Set'),
-  '#description' => t('Choose from one of the nucleotide 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 sequences. '),
-  '#collapsible' => TRUE, 
-  '#collapsed' => FALSE,  
-);
-  
-$options = _DB_options();
-$form['DB']['SELECT_DB'] = array(
- '#type' => 'select',
- '#title' => t('Nucleotide BLAST Databases:'),
- '#options' => $options,
- '#default_value' => 0,
-);
-  
-// Upload a file as an alternative to enter a query sequence 
-$form['#attributes']['enctype'] = 'multipart/form-data';
-$form['DB']['DBUPLOAD'] = array(
+  // BLAST DATABASE
+  //.........................
+
+  $form['DB'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Choose Search Set'),
+    '#description' => t('Choose from one of the nucleotide 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 sequences. '),
+    '#collapsible' => TRUE,
+    '#collapsed' => FALSE,
+  );
+
+  $options = _DB_options();
+  $form['DB']['SELECT_DB'] = array(
+    '#type' => 'select',
+    '#title' => t('Nucleotide BLAST Databases:'),
+    '#options' => $options,
+    '#default_value' => 0,
+  );
+
+  // Upload a file as an alternative to enter a query sequence
+  $form['#attributes']['enctype'] = 'multipart/form-data';
+  $form['DB']['DBUPLOAD'] = array(
    '#prefix' => 'Or upload your own dataset:	',
-  	'#type' => 'file',
-  	'#description' => t('The file should be a plain-text FASTA file and not a .doc, .docx, etc. It cannot be greater than 10 Mb in size.'),
+    '#type' => 'file',
+    '#description' => t('The file should be a plain-text FASTA file and not a .doc, .docx, etc. It cannot be greater than 10 Mb in size.'),
+  );
+
+  // ALGORITHM PARAMETERS
+  //.........................
+
+  $form['ALG'] = array(
+   '#type' => 'fieldset',
+   '#title' => t('Algorithm parameters'),
+   '#collapsible' => TRUE,
+   '#collapsed' => TRUE,
   );
-  
-//Algorithm parameters
-
-$form['ALG'] = array(
- '#type' => 'fieldset',
- '#title' => t('Algorithm parameters'),
- '#collapsible' => TRUE, 
- '#collapsed' => TRUE,  
-);
-
-//General parameters  
-
-$form['ALG']['GParam'] = array(
- '#type' => 'fieldset',
- '#title' => t('General parameters'),
- '#collapsible' => FALSE,
-);
-  
-$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,
- '#description' => t('Select the maximum number of aligned sequences to display'),
-);
-  
-$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 (Expected Threshold)'), 
-  '#default_value' => 10, 
-  '#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>'),
-);
-	
-$form['ALG']['GParam']['wordSize'] = array(
+
+  // General parameters
+
+  $form['ALG']['GParam'] = array(
+   '#type' => 'fieldset',
+   '#title' => t('General parameters'),
+   '#collapsible' => FALSE,
+  );
+
+  $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,
+    '#description' => t('Select the maximum number of aligned sequences to display'),
+  );
+
+  $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 (Expected Threshold)'),
+    '#default_value' => 10,
+    '#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>'),
+  );
+
+  $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'),
+      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,
     '#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.'),
+  );
+
+  // Scoring parameters
+
+  $form['ALG']['SParam'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Scoring parameters'),
+    '#collapsible' => FALSE,
+  );
+
+  $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,
+    '#description' => t('Reward and penalty for matching and mismatching bases.'),
    );
-  
-$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.'),
-);
- 
-// Scoring parameters
-
-$form['ALG']['SParam'] = array(
-  '#type' => 'fieldset',
-  '#title' => t('Scoring parameters'),
-  '#collapsible' => FALSE, 
-);
-  
-$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,
-  '#description' => t('Reward and penalty for matching and mismatching bases.'),
- );
-  
- $form['ALG']['SParam']['gapCost'] = array(
+
+   $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'),
+      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,
     '#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.'),
-);
-  
-//Submit 
+  );
 
+  // Submit
   $form['submit'] = array(
     '#type' => 'submit',
     '#default_value' => ' BLAST ',
   );
-  
+
   return $form;
 }
 
 /**
  * Form validation handler for blast_nucleotide_form().
  *
- * @see blast_nucleotide_form_validate()
+ * @see blast_nucleotide_form().
  */
 function blast_nucleotide_form_validate($form, &$form_state) {
-   $fastaSeq = $form_state['input']['FASTA'];
-   if (isset($fastaSeq)) {
-      if(_validateFasta($fastaSeq)){
-          form_set_error('nBLAST', t('Error: Failed to read the Blast query: Wrong format provided for FASTA nucleotide sequence'));
-      } else {
-	//$seq_filename = "/tmp/user__query_file.fasta";
-	//file_put_contents ( $seq_filename , $fastaSeq);
-        $form_state['qFlag'] = 'seqQuery';
-      }  
-   }
-   $upQuery = file_save_upload('UPLOAD', array('file_validate_extensions' => array('txt fasta fa fna')), FILE_EXISTS_RENAME);
-   if ($upQuery) {
-      $upQuery_uri = $upQuery->uri;
-      $form_state['upQuery_path'] = drupal_realpath($upQuery_uri);
-      $upQuery_content = file_get_contents($form_state['upQuery_path']);
-      if(_validateFasta($upQuery_content)){
-          form_set_error('nBLAST', t('Error: Failed to upload the Blast query: Wrong format provided for FASTA nucleotide sequence'));
-      } else {
-         $form_state['qFlag'] = 'upQuery';
-      }
-   }
-   
-   $upDB = file_save_upload('DBUPLOAD', array('file_validate_extensions' => array('txt fasta fa fna')), FILE_EXISTS_RENAME);
-   if ($upDB) {  
-      $upDB_uri = $upDB->uri;
-      $form_state['upDB_path'] = drupal_realpath($upDB_uri);
-      $upDB_content = file_get_contents($form_state['upDB_path']); 
-      if(_validateFasta($upDB_content)){
-         form_set_error('DB', t('Error: Failed to upload the Blast subject sequence file: Wrong format provided for FASTA nucleotide sequence'));
-      } else {
-         $form_state['dbFlag'] = 'upQuery';
-      }
-   } else {
-      $form_state['dbFlag'] = 'blastdb';
-   }
-      
+
+  // Validate FASTA seq in textfield
+  $fastaSeq = $form_state['input']['FASTA'];
+  if (isset($fastaSeq)) {
+    if (_validateFasta($fastaSeq)){
+      form_set_error('nBLAST', t('Error: Failed to read the Blast query: Wrong format provided for FASTA nucleotide sequence'));
+    }
+    else {
+      $form_state['qFlag'] = 'seqQuery';
+    }
+  }
+
+  // Validate query upload
+  $upQuery = file_save_upload('UPLOAD', array('file_validate_extensions' => array('txt fasta fa fna')), FILE_EXISTS_RENAME);
+  if ($upQuery) {
+    $upQuery_uri = $upQuery->uri;
+    $form_state['upQuery_path'] = drupal_realpath($upQuery_uri);
+    $upQuery_content = file_get_contents($form_state['upQuery_path']);
+    if (_validateFasta($upQuery_content)){
+      form_set_error('nBLAST', t('Error: Failed to upload the Blast query: Wrong format provided for FASTA nucleotide sequence'));
+    }
+    else {
+      $form_state['qFlag'] = 'upQuery';
+    }
+  }
+
+  // Validate blast database upload
+  $upDB = file_save_upload('DBUPLOAD', array('file_validate_extensions' => array('txt fasta fa fna')), FILE_EXISTS_RENAME);
+  if ($upDB) {
+    $upDB_uri = $upDB->uri;
+    $form_state['upDB_path'] = drupal_realpath($upDB_uri);
+    $upDB_content = file_get_contents($form_state['upDB_path']);
+    if (_validateFasta($upDB_content)){
+      form_set_error('DB', t('Error: Failed to upload the Blast subject sequence file: Wrong format provided for FASTA nucleotide sequence'));
+    }
+    else {
+      $form_state['dbFlag'] = 'upQuery';
+    }
+  }
+  else {
+    $form_state['dbFlag'] = 'blastdb';
+  }
+
 }
 
 /**
- * Form submition handler for blast_nucleotide_form().
+ * Form submission handler for blast_nucleotide_form().
  *
- * @see blast_nucleotide_form_submit()
+ * @see blast_nucleotide_form().
  */
-function blast_nucleotide_form_submit($form, &$form_state) {  
-  exec("export BLASTDB=/home/Sequences/blast_dbs/"); 
+function blast_nucleotide_form_submit($form, &$form_state) {
+
+  // SHOULDN'T BE HARDCODED!!
+  exec("export BLASTDB=/home/Sequences/blast_dbs/");
+
+
   $eVal = $form_state['values']['eVal'];
-  
+
   $trgtKey = $form_state['values']['maxTarget'];
   $numAlign = $form['ALG']['GParam']['maxTarget']['#options'][$trgtKey];
-  
+
   $wsKey = $form_state['values']['wordSize'];
   $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:
@@ -281,7 +297,9 @@ function blast_nucleotide_form_submit($form, &$form_state) {
       $gapExtend = 1;
       break;
   }
-  
+
+  // 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:
@@ -309,32 +327,44 @@ function blast_nucleotide_form_submit($form, &$form_state) {
       $reward = 1;
       break;
   }
-  
+
+  // If the query was submitted via the texrfield then create a file containing it
   if ( isset($form_state['qFlag']) ) {
-     if ( $form_state['qFlag'] == 'seqQuery' ) {
-        $seq_content = $form_state['values']['FASTA'];
-	$query = "/tmp/user__query_file.fasta";
-        file_put_contents ( $query , $seq_content);
-     } elseif ( $form_state['qFlag'] == 'upQuery' ) {
-        $query = $form_state['upQuery_path'];
-     }
+    if ( $form_state['qFlag'] == 'seqQuery' ) {
+      $seq_content = $form_state['values']['FASTA'];
+	    $query = "/tmp/user__query_file.fasta";
+      file_put_contents ( $query , $seq_content);
+    }
+    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'] == 'upQuery') {
+
      $subjectSeq = $form_state['upDB_path'];
      $subSeqOut = drupal_basename($form_state['upDB_path']) . rand(0, 10000);
+
      $blast_subj_cmd = "blastn -query $query -subject $subjectSeq -out sites/default/files/$subSeqOut.blastn.html -evalue $eVal -word_size $wordSize -gapopen $gapOpen -gapextend $gapExtend -penalty $penalty -reward $reward -num_alignments 100 -html";
      system($blast_subj_cmd);
-  } elseif ($form_state['dbFlag'] == 'blastdb') {
+
+  }
+  // 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_path = $blastdb_node->db_path;     
+     $blastdb_path = $blastdb_node->db_path;
      $blastdb_human_name = $form['DB']['SELECT_DB']['#options'][$selected_db];
      $subSeqOut = str_replace(' ','_', $blastdb_human_name) . rand(0, 10000);
+
      $blast_db_cmd = "blastn -task blastn -query $query -db $blastdb_path -out sites/default/files/$subSeqOut.blastn.xml -evalue $eVal -word_size $wordSize -gapopen $gapOpen -gapextend $gapExtend -penalty $penalty -reward $reward -num_alignments 100 -outfmt=5";
      system($blast_db_cmd,$input);
   }
 
+  // Redirect to the BLAST results page
   $path = "$subSeqOut.blastn.xml";
   drupal_goto("blast/report/$path");
 }
@@ -343,15 +373,15 @@ function blast_nucleotide_form_submit($form, &$form_state) {
 /**
  * FASTA validating parser
  *
- * @param $sequence 
- *  A string of characters to be validated. A sequence in FASTA format begins with a single-line description, followed by lines of sequence data. 
- *  The description line is distinguished from the sequence data by a greater-than (">") symbol in the first column. 
- *  The word following the ">" symbol is the identifier of the sequence, and the rest of the line is the description (both are optional). 
- *  There should be no space between the ">" and the first letter of the identifier. The sequence ends if another line starting with a ">" appears; 
+ * @param $sequence
+ *  A string of characters to be validated. A sequence in FASTA format begins with a single-line description, followed by lines of sequence data.
+ *  The description line is distinguished from the sequence data by a greater-than (">") symbol in the first column.
+ *  The word following the ">" symbol is the identifier of the sequence, and the rest of the line is the description (both are optional).
+ *  There should be no space between the ">" and the first letter of the identifier. The sequence ends if another line starting with a ">" appears;
  *  this indicates the start of another sequence.
  *
  * @return
- *  Return a boolean. 1 if the sequence does not pass the format valifation stage and 0 otherwise.   
+ *  Return a boolean. 1 if the sequence does not pass the format valifation stage and 0 otherwise.
  *
  */
 function _validateFasta($sequence) {
@@ -362,33 +392,32 @@ function _validateFasta($sequence) {
   } else {
    $flag = 0;
   }
-	
+
   return $flag;
 }
 
 
 /**
- * Load the preexisting blast databases 
+ * Generate an array of BLAST database options based on existing nodes of type BlastDB
  *
  * @return
- *  Return human readble names of the preexisting blast databases   
- *
+ *  Return human readble names of the pre-existing blast databases
  */
 function _DB_options() {
-   $type = 'blastdb';
-   $nodes  = node_load_multiple(array(), array('type'=> $type));
-   $options = array();
-
-   foreach ($nodes as $node) {
-      if ( isset($node) && isset($node->db_dbtype) ) {
-	if ( ($node->db_dbtype=='n') ) {
-         $options[$node->nid] = $node->db_name;
-	}
-      }     
-   }
-
-   asort($options);
-   $options[0] = 'Select a Dataset';
-
-   return $options;
+  $type = 'blastdb';
+  $nodes  = node_load_multiple(array(), array('type'=> $type));
+  $options = array();
+
+  foreach ($nodes as $node) {
+    if ( isset($node) && isset($node->db_dbtype) ) {
+	    if ( ($node->db_dbtype=='n') ) {
+        $options[$node->nid] = $node->db_name;
+	    }
+    }
+  }
+
+  asort($options);
+  $options[0] = 'Select a Dataset';
+
+  return $options;
 }

+ 218 - 201
includes/blast_ui.blastp.inc

@@ -2,88 +2,90 @@
 
 /**
  * @file
- * Contains all functions for the protein blast module 
+ * Contains all functions for the Protein BLAST
  */
 
 
 /**
- * Form constructor for the protein blast form.
+ * Protein BLAST Submission Form
  *
  * @see blast_protein_form_validate()
  * @see blast_protein_form_submit()
- *
  */
 function blast_protein_form($form, &$form_state) {
-  
-// Protein BLAST
 
-$form['pBLAST'] = array(
+  // PROTEIN QUERY
+  //.........................
+
+  $form['query'] = array(
     '#type' => 'fieldset',
     '#title' => t('Enter Query Sequence'),
     '#description' => t('Enter one or more queries in the top text box or use the browse button to upload a file from your local disk. The file may contain a single sequence or a list of sequences. In both cases, the data must be in FASTA format. <a href="http://www.ncbi.nlm.nih.gov/BLAST/blastcgihelp.shtml" target="_blank">More information..</a> '),
-    '#collapsible' => TRUE, 
-    '#collapsed' => FALSE,  
+    '#collapsible' => TRUE,
+    '#collapsed' => FALSE,
   );
 
-$form['pBLAST']['FASTA'] = array(
+  $form['query']['FASTA'] = array(
     '#type' => 'textarea',
     '#title' => t('Enter FASTA sequence(s)'),
     '#description'=>t('Enter query sequence(s) in the text area.'),
   );
 
-// Upload a file as an alternative to enter a query sequence 
-$form['#attributes']['enctype'] = 'multipart/form-data';
-$form['pBLAST']['UPLOAD'] = array(
+  // Upload a file as an alternative to enter a query sequence
+  $form['#attributes']['enctype'] = 'multipart/form-data';
+  $form['query']['UPLOAD'] = array(
   	'#prefix' => 'Or upload your query files:	',
   	'#type' => 'file',
   	'#description' => t('The file should be a plain-text FASTA file and not a .doc, .docx, etc. It cannot be greater than 10 Mb in size.'),
   );
 
 
-//DATABASE//
-
-$form['DB'] = array(
-  '#type' => 'fieldset',
-  '#title' => t('Choose Search Set'),
-  '#description' => t('Choose from one of the protein 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 sequences. '),
-  '#collapsible' => TRUE, 
-  '#collapsed' => FALSE,  
-);
-  
-$options = DB_options();
-$form['DB']['SELECT_DB'] = array(
- '#type' => 'select',
- '#title' => t('Protein BLAST Databases:'),
- '#options' => $options,
- '#default_value' => t('Select a database'),
-);
-  
-// Upload a file as an alternative to enter a query sequence 
-$form['#attributes']['enctype'] = 'multipart/form-data';
-$form['DB']['DBUPLOAD'] = array(
+  // BLAST DATABASE
+  //.........................
+
+  $form['DB'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Choose Search Set'),
+    '#description' => t('Choose from one of the protein 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 sequences. '),
+    '#collapsible' => TRUE,
+    '#collapsed' => FALSE,
+  );
+
+  $options = DB_options();
+  $form['DB']['SELECT_DB'] = array(
+  '#type' => 'select',
+   '#title' => t('Protein BLAST Databases:'),
+   '#options' => $options,
+   '#default_value' => t('Select a database'),
+  );
+
+  // Upload a file as an alternative to enter a query sequence
+  $form['#attributes']['enctype'] = 'multipart/form-data';
+  $form['DB']['DBUPLOAD'] = array(
    '#prefix' => 'Or upload your own dataset:	',
   	'#type' => 'file',
   	'#description' => t('The file should be a plain-text FASTA file and not a .doc, .docx, etc. It cannot be greater than 10 Mb in size.'),
-);
-  
-//Algorithm parameters
+  );
+
+  // ALGORITHM PARAMETERS
+  //.........................
 
 	$form['ALG'] = array(
     '#type' => 'fieldset',
     '#title' => t('Algorithm parameters'),
-    '#collapsible' => TRUE, 
-    '#collapsed' => TRUE,  
-);
+    '#collapsible' => TRUE,
+    '#collapsed' => TRUE,
+  );
 
-//General parameters  
+  //General parameters
 
- $form['ALG']['GParam'] = array(
+  $form['ALG']['GParam'] = array(
     '#type' => 'fieldset',
     '#title' => t('General parameters'),
     '#collapsible' => FALSE,
- );
-  
-$form['ALG']['GParam']['maxTarget'] = array(
+  );
+
+  $form['ALG']['GParam']['maxTarget'] = array(
     '#type' => 'select',
     '#title' => t('Max target sequences:'),
     '#options' => array(
@@ -99,24 +101,24 @@ $form['ALG']['GParam']['maxTarget'] = array(
     ),
     '#default_value' => 2,
     '#description' => t('Select the maximum number of aligned sequences to display'),
-);
-  
-$form['ALG']['GParam']['shortQueries'] = array(
-   '#type' => 'checkbox', 
+  );
+
+  $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, 
+  );
+
+  $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.'),
-);
-	
-$form['ALG']['GParam']['wordSize'] = array(
+  );
+
+  $form['ALG']['GParam']['wordSize'] = array(
     '#type' => 'select',
     '#title' => t('Word size:'),
     '#options' => array(
@@ -125,71 +127,70 @@ $form['ALG']['GParam']['wordSize'] = array(
     ),
     '#default_value' => 1,
     '#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, 
+  );
+
+  $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.'),
-);
- 
-// Scoring parameters
+  );
 
-$form['ALG']['SParam'] = array(
+  // Scoring parameters
+
+  $form['ALG']['SParam'] = array(
    '#type' => 'fieldset',
    '#title' => t('Scoring parameters'),
-   '#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(
-   '#type' => 'select',
-   '#title' => 'Matrix',
-   '#options' => $options_first,
-   '#default_value' => $selected,
-   '#description' => t('Assigns a score for aligning pairs of residues, and determines overall alignment score..'),
-   '#ajax' => array(
+   '#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(
+    '#type' => 'select',
+    '#title' => 'Matrix',
+    '#options' => $options_first,
+    '#default_value' => $selected,
+    '#description' => t('Assigns a score for aligning pairs of residues, and determines overall alignment score..'),
+    '#ajax' => array(
       'callback' => 'ajax_example_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' => _ajax_example_get_second_dropdown_options($selected),
-   '#default_value' => 2,
-   '#description' => t('Cost to create and extend a gap in an alignment.'),
-);
-  
-$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'),
-);
-  
-//Submit 
-
-$form['submit'] = array(
-   '#type' => 'submit',
-   '#default_value' => ' BLAST ',
-);
-  
-return $form;
+    ),
+  );
+
+  $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),
+    '#default_value' => 2,
+    '#description' => t('Cost to create and extend a gap in an alignment.'),
+  );
+
+  $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'),
+  );
+
+  //Submit
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#default_value' => ' BLAST ',
+  );
+
+  return $form;
 }
 
 /**
@@ -198,40 +199,49 @@ return $form;
  * @see blast_protein_form_validate()
  */
 function blast_protein_form_validate($form, &$form_state) {
-   $fastaSeq = $form_state['input']['FASTA'];
-   if (isset($fastaSeq)) {
-      if(validateFasta($fastaSeq)){
-          form_set_error('pBLAST', t('Error: Failed to read the Blast query: Wrong format provided for FASTA protein sequence'));
-      } else {
-        $form_state['qFlag'] = 'seqQuery';
-      }  
-   }
-   $upQuery = file_save_upload('UPLOAD', array('file_validate_extensions' => array('txt fasta fa fna')), FILE_EXISTS_RENAME);
-   if ($upQuery) {
-      $upQuery_uri = $upQuery->uri;
-      $form_state['upQuery_path'] = drupal_realpath($upQuery_uri);
-      $upQuery_content = file_get_contents($form_state['upQuery_path']);
-      if(validateFasta($upQuery_content)){
-          form_set_error('pBLAST', t('Error: Failed to upload the Blast query: Wrong format provided for FASTA protein sequence'));
-      } else {
-         $form_state['qFlag'] = 'upQuery';
-      }
-   }
-   
-   $upDB = file_save_upload('DBUPLOAD', array('file_validate_extensions' => array('txt fasta fa fna')), FILE_EXISTS_RENAME);
-   if ($upDB) {  
-      $upDB_uri = $upDB->uri;
-      $form_state['upDB_path'] = drupal_realpath($upDB_uri);
-      $upDB_content = file_get_contents($form_state['upDB_path']); 
-      if(validateFasta($upDB_content)){
-         form_set_error('DB', t('Error: Failed to upload the Blast subject sequence file: Wrong format provided for FASTA protein sequence'));
-      } else {
-         $form_state['dbFlag'] = 'upQuery';
-      }
-   } else {
-      $form_state['dbFlag'] = 'blastdb';
-   }
-      
+
+  // Validate query sequence
+  $fastaSeq = $form_state['input']['FASTA'];
+  if (isset($fastaSeq)) {
+    if (validateFasta($fastaSeq)){
+      form_set_error('pBLAST', t('Error: Failed to read the Blast query: Wrong format provided for FASTA protein sequence'));
+    }
+    else {
+      $form_state['qFlag'] = 'seqQuery';
+    }
+  }
+
+  // Validate Query Upload
+  $upQuery = file_save_upload('UPLOAD', array('file_validate_extensions' => array('txt fasta fa fna')), FILE_EXISTS_RENAME);
+  if ($upQuery) {
+    $upQuery_uri = $upQuery->uri;
+    $form_state['upQuery_path'] = drupal_realpath($upQuery_uri);
+    $upQuery_content = file_get_contents($form_state['upQuery_path']);
+    if(validateFasta($upQuery_content)){
+      form_set_error('pBLAST', t('Error: Failed to upload the Blast query: Wrong format provided for FASTA protein sequence'));
+    }
+    else {
+      $form_state['qFlag'] = 'upQuery';
+    }
+  }
+
+  // Validate uploaded database
+  $upDB = file_save_upload('DBUPLOAD', array('file_validate_extensions' => array('txt fasta fa fna')), FILE_EXISTS_RENAME);
+  if ($upDB) {
+    $upDB_uri = $upDB->uri;
+    $form_state['upDB_path'] = drupal_realpath($upDB_uri);
+    $upDB_content = file_get_contents($form_state['upDB_path']);
+    if(validateFasta($upDB_content)){
+      form_set_error('DB', t('Error: Failed to upload the Blast subject sequence file: Wrong format provided for FASTA protein sequence'));
+    }
+    else {
+      $form_state['dbFlag'] = 'upQuery';
+    }
+  }
+  else {
+    $form_state['dbFlag'] = 'blastdb';
+  }
+
 }
 
 /**
@@ -239,19 +249,21 @@ function blast_protein_form_validate($form, &$form_state) {
  *
  * @see blast_protein_form_submit()
  */
-function blast_protein_form_submit($form, &$form_state) {  
+function blast_protein_form_submit($form, &$form_state) {
+
   $eVal = $form_state['values']['eVal'];
-  
+
   $trgtKey = $form_state['values']['maxTarget'];
   $numAlign = $form['ALG']['GParam']['maxTarget']['#options'][$trgtKey];
-  
+
   $wsKey = $form_state['values']['wordSize'];
   $wordSize = $form['ALG']['GParam']['wordSize']['#options'][$wsKey];
-  
+
+  // Expand Gap Cost key into open and extend penalties
   $gapKey = $form_state['values']['MATRIX'];
   switch ($gapKey) {
    case 0:
-     $matrix ="PAM30"; 
+     $matrix ="PAM30";
      $gapKey = $form_state['values']['gapCost'];
      switch ($gapKey) {
       case 0:
@@ -311,7 +323,7 @@ function blast_protein_form_submit($form, &$form_state) {
      }
      break;
    case 2:
-     $matrix ="PAM250"; 
+     $matrix ="PAM250";
      $gapKey = $form_state['values']['gapCost'];
      switch ($gapKey) {
       case 0:
@@ -407,7 +419,7 @@ function blast_protein_form_submit($form, &$form_state) {
      }
       break;
    case 4:
-     $matrix ="BLOSUM62"; 
+     $matrix ="BLOSUM62";
      $gapKey = $form_state['values']['gapCost'];
      switch ($gapKey) {
       case 0:
@@ -457,7 +469,7 @@ function blast_protein_form_submit($form, &$form_state) {
      }
       break;
    case 5:
-     $matrix ="BLOSUM45"; 
+     $matrix ="BLOSUM45";
      $gapKey = $form_state['values']['gapCost'];
      switch ($gapKey) {
       case 0:
@@ -511,7 +523,7 @@ function blast_protein_form_submit($form, &$form_state) {
      }
      break;
    case 6:
-     $matrix ="BLOSUM50"; 
+     $matrix ="BLOSUM50";
      $gapKey = $form_state['values']['gapCost'];
      switch ($gapKey) {
       case 0:
@@ -577,7 +589,7 @@ function blast_protein_form_submit($form, &$form_state) {
      }
      break;
    case 7:
-     $matrix ="BLOSUM90"; 
+     $matrix ="BLOSUM90";
      $gapKey = $form_state['values']['gapCost'];
      switch ($gapKey) {
       case 0:
@@ -611,33 +623,44 @@ function blast_protein_form_submit($form, &$form_state) {
      }
      break;
   }
-  
+
+  // If the query was submitted via the texrfield then create a file containing it
   if ( isset($form_state['qFlag']) ) {
-     if ( $form_state['qFlag'] == 'seqQuery' ) {
-        $seq_content = $form_state['values']['FASTA'];
-	$query = "/tmp/user__query_file.fasta";
-        file_put_contents ( $query , $seq_content);
-     } elseif ( $form_state['qFlag'] == 'upQuery' ) {
-        $query = $form_state['upQuery_path'];
-     }
+    if ( $form_state['qFlag'] == 'seqQuery' ) {
+      $seq_content = $form_state['values']['FASTA'];
+	    $query = "/tmp/user__query_file.fasta";
+      file_put_contents ( $query , $seq_content);
+    }
+    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'] == 'upQuery') {
+
      $subjectSeq = $form_state['upDB_path'];
      $subSeqOut = drupal_basename($form_state['upDB_path']) . rand(0, 10000);
+
      $blast_subj_cmd = "blastp -task blastp -query $query -subject $subjectSeq -out sites/default/files/$subSeqOut.blastp.html";
-// -evalue $eVal -word_size $wordSize -gapopen $gapOpen -gapextend $gapExtend -matrix $matrix -num_alignments 100 -html";
      system($blast_subj_cmd);
-  } elseif ($form_state['dbFlag'] == 'blastdb') {
+
+  }
+  // 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_path = $blastdb_node->db_path;     
+     $blastdb_path = $blastdb_node->db_path;
      $blastdb_human_name = $form['DB']['SELECT_DB']['#options'][$selected_db];
      $subSeqOut = str_replace(' ','_', $blastdb_human_name) . rand(0, 10000);
+
      $blast_db_cmd = "blastp -task blastp -query $query -db $blastdb_path -out sites/default/files/$subSeqOut.blastp.html -evalue $eVal -word_size $wordSize -gapopen $gapOpen -gapextend $gapExtend -matrix $matrix -num_alignments 100 -html";
      system($blast_db_cmd,$input);
   }
 
+  // Redirect to the BLAST Results page
   $path = "$subSeqOut.blastp.html";
   drupal_goto("blast/report/$path");
 }
@@ -646,46 +669,46 @@ function blast_protein_form_submit($form, &$form_state) {
 /**
  * FASTA validating parser
  *
- * @param $sequence 
- *  A string of characters to be validated. A sequence in FASTA format begins with a single-line description, followed by lines of sequence data. 
- *  The description line is distinguished from the sequence data by a greater-than (">") symbol in the first column. 
- *  The word following the ">" symbol is the identifier of the sequence, and the rest of the line is the description (both are optional). 
- *  There should be no space between the ">" and the first letter of the identifier. The sequence ends if another line starting with a ">" appears; 
+ * @param $sequence
+ *  A string of characters to be validated. A sequence in FASTA format begins with a single-line description, followed by lines of sequence data.
+ *  The description line is distinguished from the sequence data by a greater-than (">") symbol in the first column.
+ *  The word following the ">" symbol is the identifier of the sequence, and the rest of the line is the description (both are optional).
+ *  There should be no space between the ">" and the first letter of the identifier. The sequence ends if another line starting with a ">" appears;
  *  this indicates the start of another sequence.
  *
  * @return
- *  Return a boolean. 1 if the sequence does not pass the format valifation stage and 0 otherwise.   
+ *  Return a boolean. 1 if the sequence does not pass the format valifation stage and 0 otherwise.
  *
  */
 function validateFasta($sequence) {
 	$fastaIdRegEx = '/^>.*(\\n|\\r)/';
 	$fastaSeqRegEx = '/[^acgturykmswbdhvnxACGTURYKMSWBDHVNX\*\-\n\r]/';
 	if ( preg_match($fastaSeqRegEx,$sequence) && !(preg_match($fastaIdRegEx,$sequence)) ) {
-      $flag = 1;
-   } else {
-      $flag = 0;
-   }
-   
+    $flag = 1;
+  } else {
+    $flag = 0;
+  }
+
   return $flag;
 }
 
 
 /**
- * Load the preexisting blast databases 
+ * Generate an array of BLAST database options based on existing nodes of type BlastDB
  *
  * @return
- *  Return human readble names of the preexisting blast databases   
+ *  Return human readble names of the pre-existing blast databases
  *
  */
 function DB_options() {
    $type = 'blastdb';
    $nodes  = node_load_multiple(array(), array('type'=> $type));
-	
+
    $options = array();
 
    foreach ($nodes as $node) {
       if ( isset($node) && isset($node->db_dbtype) ) {
-        if ( ($node->db_dbtype=='p') ) {                         
+        if ( ($node->db_dbtype=='p') ) {
          $options[$node->nid] = $node->db_name;
         }
       }
@@ -698,15 +721,14 @@ function DB_options() {
 }
 
 /**
- * Fill the first dropdown list with appropriate options  
+ * Fill the first dropdown list with appropriate options
  *
  * @return
- * An array consisting of matrices name for the first dropdown list   
- *
+ * An array consisting of matrices name for the first dropdown list
  */
 function _ajax_example_get_first_dropdown_options() {
   return drupal_map_assoc(array(
-  t('PAM30'),	
+  t('PAM30'),
   t('PAM70'),
   t('PAM250'),
   t('BLOSUM80'),
@@ -718,11 +740,10 @@ function _ajax_example_get_first_dropdown_options() {
 }
 
 /**
- * Fill the second dropdown list with appropriate options  
+ * Fill the second dropdown list with appropriate options
  *
  * @return
- * An array containing open and extension gap values for the chosen matrix (to fill the second dropdown list)   
- *
+ * 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 = '') {
   $options = array(
@@ -829,11 +850,7 @@ function _ajax_example_get_second_dropdown_options($key = '') {
 }
 
 /**
- * Respond to Ajax dropdown call 
- *
- * @return
- *     
- *
+ * Respond to Ajax dropdown call
  */
 function ajax_example_dependent_dropdown_callback($form, $form_state) {
   return $form['ALG']['SParam']['gapCost'];

+ 27 - 32
includes/blast_ui.node.inc

@@ -7,9 +7,7 @@
 
 
 /**
- *
- * Implements hook_node_info()
- * 
+ * Implements hook_node_info().
  */
 function blast_ui_node_info() {
   return array(
@@ -21,6 +19,9 @@ function blast_ui_node_info() {
   );
 }
 
+/**
+ * Implements hook_node_access().
+ */
 function blastdb_node_access($node, $op, $account) {
   $node_type = $node;
   if (is_object($node)) {
@@ -61,17 +62,17 @@ function blastdb_node_access($node, $op, $account) {
  * @see blastdb_update()
  * @see blastdb_delete()
  * @see blastdb_load()
- *
  */
 function blastdb_form($node, &$form_state) {
   $form = array();
-  
+
   $form['db_name']= array(
     '#type' => 'textfield',
     '#title' => t('Human-readable Name for Blast database'),
     '#required' => TRUE,
     '#default_value' => isset($node->db_name) ? $node->db_name : '',
   );
+
   $form['db_path']= array(
     '#type' => 'textfield',
     '#title' => t('File Prefix including Full Path'),
@@ -79,26 +80,26 @@ function blastdb_form($node, &$form_state) {
     '#required' => TRUE,
     '#default_value' => isset($node->db_path) ? $node->db_path : '',
   );
+
   $form['db_dbtype'] = array(
-	'#type' => 'radios',
-	'#title' => t('Type of the blast database'),
-	'#options' => array(
-		'n' => t('Nucleotide'),
-		'p' => t('Protein'),
-	),
-	'#required' => TRUE,
-	'#default_value' => isset($node->db_dbtype) ? $node->db_dbtype : 'n',
+    '#type' => 'radios',
+    '#title' => t('Type of the blast database'),
+    '#options' => array(
+      'n' => t('Nucleotide'),
+      'p' => t('Protein'),
+    ),
+    '#required' => TRUE,
+    '#default_value' => isset($node->db_dbtype) ? $node->db_dbtype : 'n',
   );
+
   return $form;
 }
 
 /**
-*
-* Implements hook_insert()
-*                                                                                                            
-*/
+ * Implements hook_insert().
+ */
 function blastdb_insert($node) {
- 
+
   db_insert('blastdb')->fields(array(
     'nid' => $node->nid,
     'name' => $node->db_name,
@@ -119,10 +120,8 @@ function blast_ui_node_insert($node) {
 }
 
 /**
-*
-* Implements hook_update()
-*                                                                                                            
-*/
+ * Implements hook_update().
+ */
 function blastdb_update($node) {
     db_update('blastdb')->fields(array(
     'name' => $node->db_name,
@@ -142,23 +141,19 @@ function blast_ui_node_update($node) {
 }
 
 /**
-*
-* Implements hook_delete()
-*                                                                                                            
-*/
+ * Implements hook_delete().
+ */
 function blastdb_delete($node) {
    db_delete('blastdb')->condition('nid',$node->nid)->execute();
 }
 
 /**
-*
-* Implements hook_load()
-*                                                                                                            
-*/
+ * Implements hook_load()   .
+ */
 function blastdb_load($nodes) {
-    
+
   $result = db_query('SELECT nid, name, path, dbtype FROM {blastdb} WHERE nid IN (:nids)', array(':nids' => array_keys($nodes)));
-  
+
   foreach ($result as $record) {
     $nodes[$record->nid]->db_name = $record->name;
     $nodes[$record->nid]->db_path = $record->path;

+ 6 - 13
theme/blast_report.css

@@ -1,3 +1,9 @@
+
+/**
+ * @file
+ * Handles CSS Themeing of the BLAST Results
+ */
+
 #blast_report h4 {
   margin: 0px;
   padding: 0px;
@@ -10,22 +16,9 @@
   padding: 0px;
 }
 #blast_report th {
-/**
-  background: #7CB8E2 url(header_bkg.png) repeat-x scroll center left;
-  color: #fff;
-  padding: 7px 50px; */
   text-align: left;
 }
-#blast_report td {
-/**
-  background:#C7DDEE none repeat-x scroll center left;
-  color:#000;
-  padding:7px 50px;
-*/
-}
 #blast_report tr.odd td {
-/**
-  background:#fff url(row_bkg.png) repeat-x scroll center left; */
   cursor:pointer;
 }
 #blast_report .arrow {

+ 28 - 9
theme/blast_report.tpl.php

@@ -1,12 +1,25 @@
 <?php
 
+/**
+ * Display the results of a BLAST job execution
+ *
+ * Variables Available in this template:
+ *   $xml_filename: The full path & filename of XML file containing the BLAST results
+ */
 ?>
 
+<!-- JQuery controlling display of the alignment information (hidden by default) -->
 <script type="text/javascript">
   $(document).ready(function(){
+
+    // Hide the alignment rows in the table
+    // (ie: all rows not labelled with the class "result-summary" which contains the tabular
+    // summary of the hit)
     $("#blast_report tr:not(.result-summary)").hide();
     $("#blast_report tr:first-child").show();
 
+    // When a results summary row is clicked then show the next row in the table
+    // which should be corresponding the alignment information
     $("#blast_report tr.result-summary").click(function(){
       $(this).next("tr").toggle();
       $(this).find(".arrow").toggleClass("up");
@@ -15,13 +28,16 @@
 </script>
 
 <?php
-//Load the XML file
-$path = current_path();
-if (preg_match('%blast/report/([\w\.]+)%',$path,$matches)) {
-  $filename = 'sites/default/files/' . $matches[1];
-  $xml=simplexml_load_file($filename);
-}
 
+// Load the XML file
+$xml = simplexml_load_file($xml_filename);
+
+/**
+ * We are using the drupal table theme functionality to create this listing
+ * @see theme_table() for additional documentation
+ */
+
+// Specify the header of the table
 $header = array(
   'number' =>  array('data' => '#', 'class' => array('number')),
   'query' =>  array('data' => 'Query Name', 'class' => array('query')),
@@ -33,6 +49,9 @@ $header = array(
 $rows = array();
 $count = 0;
 
+// 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($iteration->{'Iteration_hits'}->children() as $hit) {
     if (is_object($hit)) {
@@ -40,13 +59,13 @@ foreach($xml->{'BlastOutput_iterations'}->children() as $iteration) {
 
       $zebra_class = ($count % 2 == 0) ? 'even' : 'odd';
 
-      // SIMPLY SUMMARY ROW
+      // SUMMARY ROW
       $hit_name = $hit->Hit_def;
       if (preg_match('/(\w+)/', $hit_name, $matches)) {
         $hit_name = $matches[1];
       }
-      $score = $hit->Hit_hsps->Hsp->Hsp_score;
-      $evalue = $hit->Hit_hsps->Hsp->Hsp_evalue;
+      $score = $hit->{'Hit_hsps'}->{'Hsp'}->{'Hsp_score'};
+      $evalue = $hit->{'Hit_hsps'}->{'Hsp'}->{'Hsp_evalue'};
       $query_name = $iteration->{'Iteration_query-def'};
 
       $row = array(

+ 5 - 0
theme/blast_report_alignment_row.tpl.php

@@ -1,6 +1,11 @@
 <?php
 /**
  * This Template generates the HTML for a single Alignment row in a BLAST report
+ *
+ * Variables Available in this template:
+ *   $HSPs: an array of HSPs for the current BLAST result. This follows the structure
+ *     layed out in the XML file but has been made an array instead of a SimpleXML object
+ *     for ease of processing and abstration.
  */
 ?>
 

+ 20 - 3
theme/blast_ui.theme.inc

@@ -1,13 +1,30 @@
 <?php
 
+/**
+ * @file
+ * This file contains functions specifically related to theme-ing the BLAST module
+ */
+
+/**
+ * Preprocess function for the show_blast_report.tpl.php
+ *
+ * Use this function to prepare variables for use in the template,
+ * as well as to add css/javascript needed.
+ *
+ * @param $vars
+ *   The variables currently available to the template.
+ */
 function blast_ui_preprocess_show_blast_report(&$vars) {
 
    $path = drupal_get_path('module', 'blast_ui');
- 
+
    drupal_add_css($path . '/theme/blast_report.css');
    drupal_add_js('http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js');
 
-}
 
+  $path = current_path();
+  if (preg_match('%blast/report/([\w\.]+)%',$path,$matches)) {
+    $vars['xml_filename'] = 'sites/default/files/' . $matches[1];
+  }
 
-?>
+}