123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486 |
- <?php
- /**
- * @file
- * Forms in the file provide a per BLAST program interface to submitting BLASTs.
- *
- * In other words, it provides a form for blastn, one for blastp, etc. It does
- * this using a single form function for code reusability and depending upon
- * the $type passed in, it will execute additional hooks allowing for program
- * specific modifications & advanced options.
- */
- /**
- * This single form definition provides 4 different program-specific forms.
- */
- 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',
- );
-
- // @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;
- }
-
- // Determine the BLAST program.
- $query_type = $form_state['build_info']['args'][0];
- $db_type = $form_state['build_info']['args'][1];
- if ($query_type == 'nucleotide') {
- if ($db_type == 'nucleotide') {
- $blast_program = 'blastn';
- }
- elseif ($db_type == 'protein') {
- $blast_program = 'blastx';
- }
- }
- elseif ($query_type == 'protein') {
- if ($db_type == 'nucleotide') {
- $blast_program = 'tblastn';
- }
- elseif ($db_type == 'protein') {
- $blast_program = 'blastp';
- }
- }
- // Set the title to be more Researcher friendly.
- drupal_set_title(t(
- '@query to @db BLAST (@program)',
- array(
- '@query' => ucfirst($query_type),
- '@db' => ucfirst($db_type),
- '@program' => $blast_program
- )
- ));
- // Add the details about the specific BLAST choosen.
- $form['query_type'] = array(
- '#type' => 'hidden',
- '#value' => $query_type
- );
- $form['db_type'] = array(
- '#type' => 'hidden',
- '#value' => $db_type
- );
- $form['blast_program'] = array(
- '#type' => 'hidden',
- '#value' => $blast_program
- );
- // NUCLEOTIDE QUERY
- //.........................
- $form['query'] = array(
- '#type' => 'fieldset',
- '#title' => t('Enter %type Query Sequence',
- array('%type' => ucfirst($query_type))),
- '#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 <a href="@formaturl" target="_blank">FASTA format</a>.',
- array(
- '@formaturl' => 'http://www.ncbi.nlm.nih.gov/BLAST/blastcgihelp.shtml'
- )
- ),
- '#collapsible' => TRUE,
- '#collapsed' => FALSE,
- );
- // Checkbox to show an example.
- $form['query']['example_sequence'] = array(
- '#type' => 'checkbox',
- '#title' => t('Show an Example Sequence'),
- '#prefix' => '<span style="float: right;">',
- '#suffix' => '</span>',
- '#ajax' => array(
- 'callback' => 'ajax_blast_ui_example_sequence_callback',
- 'wrapper' => 'fasta-textarea',
- 'method' => 'replace',
- 'effect' => 'fade',
- ),
- );
- // 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.'),
- '#default_value' => isset($job_data[$jid]['fasta']) ? $job_data[$jid]['fasta'] : '',
- '#prefix' => '<div id="fasta-textarea">',
- '#suffix' => '</div>',
- );
- // 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: ',
- '#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
- 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>',
- array(
- '%max_size' => round(file_upload_max_size() / 1024 / 1024,1) . 'MB'
- )
- ),
- '#upload_validators' => array(
- 'file_validate_extensions' => array('fasta fna fa'),
- 'file_validate_size' => array(file_upload_max_size()),
- ),
- );
- // BLAST DATABASE
- //.........................
- $form['DB'] = array(
- '#type' => 'fieldset',
- '#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 '
- . 'sequences. ',
- array('%type' => $db_type)),
- '#collapsible' => TRUE,
- '#collapsed' => FALSE,
- );
- $options = get_blast_database_options($db_type);
- $form['DB']['SELECT_DB'] = array(
- '#type' => 'select',
- '#title' => t('%type BLAST Databases:', array('%type' => ucfirst($db_type))),
- '#options' => $options,
- '#default_value' => isset($job_data[$jid]['db_option']) ? $job_data[$jid]['db_option'] : 0,
- );
- if (variable_get('blast_ui_allow_target_upload', FALSE)) {
- // 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: ',
- '#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
- 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>',
- array(
- '%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()),
- ),
- );
- }
- // Advanced Options
- //.........................
- // These options will be different depending upon the program selected.
- // Therefore, allow for program-specific callbacks to populate these options.
- $form['ALG'] = array(
- '#type' => 'fieldset',
- '#title' => t('Advanced Options'),
- '#collapsible' => TRUE,
- '#collapsed' => TRUE,
- );
- $advanced_options_form = 'blast_ui_' . $blast_program . '_advanced_options_form';
- if (function_exists($advanced_options_form)) {
- call_user_func_array($advanced_options_form, array(&$form, $form_state));
- }
- // Submit
- //.........................
- $form['submit'] = array(
- '#type' => 'submit',
- '#default_value' => ' BLAST ',
- );
- return $form;
- }
- /**
- * Validate the user options submitted via the above form.
- *
- * @see blast_ui_per_blast_program_form().
- */
- function blast_ui_per_blast_program_form_validate($form, &$form_state) {
- $blast_program = $form_state['values']['blast_program'];
- $type = $form_state['values']['query_type'];
- if ($type == 'nucleotide') {
- $molecule_type = 'nucleotides';
- }
- else {
- $molecule_type = 'amino acid residues';
- }
- // Validate Query
- //----------------
- // @todo: We are currently not validating uploaded files are valid FASTA.
- // First check to see if we have an upload & if so then validate it.
- $file = file_load($form_state['values']['UPLOAD']);
- // If the $file is populated then this is a newly uploaded, temporary file.
- if (is_object($file)) {
- $form_state['qFlag'] = 'upQuery';
- $form_state['upQuery_path'] = drupal_realpath($file->uri);
- }
- // Otherwise there was no file uploaded.
- // Check if there was a query sequence entered in the texfield.
- elseif (!empty($form_state['input']['FASTA'])) {
- // Check to ensure that the query sequence entered is valid FASTA.
- if (validate_fasta_sequence($type, $form_state['input']['FASTA'])){
- form_set_error('query', t('You need to provide a valid FASTA sequence '
- . 'for the query. It should contain a FASTA header/definition line '
- . 'followed by %molecule-type. For more information see the '
- . '<a href="@url" target="_blank">NCBI FASTA Specification</a>.',
- array(
- '%molecule-type' => $molecule_type,
- '@url' => 'http://www.ncbi.nlm.nih.gov/BLAST/blastcgihelp.shtml'
- )));
- }
- else {
- $form_state['qFlag'] = 'seqQuery';
- }
- }
- // Otherwise they didn't enter a query!!
- else {
- form_set_error('query', t('No query sequence given. Only raw sequence or '
- . 'sequence of type FASTA can be read. Enter sequence in the box provided '
- . 'or upload a plain text file.'));
- }
- // Validate Database
- //-------------------
- // @todo: We are currently not validating uploaded files are valid FASTA.
- // First check to see if we have an upload & if so then validate it.
- if (isset($form_state['values']['DBUPLOAD'])) {
- $file = file_load($form_state['values']['DBUPLOAD']);
- // If the $file is populated then this is a newly uploaded, temporary file.
- if (is_object($file)) {
- $form_state['dbFlag'] = 'upDB';
- $form_state['upDB_path'] = drupal_realpath($file->uri);
- }
- // Otherwise there was no file uploaded
- // Check if there was a database choosen from the list instead
- elseif (!empty($form_state['values']['SELECT_DB'])) {
- $form_state['dbFlag'] = 'blastdb';
- }
- // Otherwise they didn't select a database!!
- else {
- form_set_error('DB', t('No database selected. Either choose a database '
- . 'from the list or upload one of your own.'));
- }
- }
- // Otherwise there was no file uploaded
- // Check if there was a database choosen from the list instead
- elseif (!empty($form_state['values']['SELECT_DB'])) {
- $form_state['dbFlag'] = 'blastdb';
- }
- // Otherwise they didn't select a database!!
- else {
- form_set_error('DB', t('No database selected. Either choose a database '
- . 'from the list or upload one of your own.'));
- }
- // Validate Advanced Options
- //---------------------------
- $advanced_options_form_validate = 'blast_ui_' . $blast_program . '_advanced_options_form_validate';
- if (function_exists($advanced_options_form_validate)) {
- call_user_func_array(
- $advanced_options_form_validate,
- array(&$form, $form_state)
- );
- }
- }
- /**
- * Process the user options submitted via the blast program form.
- *
- * @see blast_ui_per_blast_program_form().
- */
- 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'; eksc- handled below
- }
- else {
- $mdb_type = 'prot';
- // $file_suffix = '.psq';
- }
- // 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/' . date('YMd_His') . '_query.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'] == 'upDB') {
- // Since we only support using the -db flag (not -subject) we need to create a
- // blast database for the FASTA uploaded.
- // NOTE: We can't support subject because we need to generate the ASN.1+ format
- // to provide multiple download type options from the same BLAST
- $blastdb_with_path = $form_state['upDB_path'];
- $result = NULL;
- exec("makeblastdb -in $blastdb_with_path -dbtype $mdb_type -parse_seqids 2>&1", $result);
- // Check that the BLAST database was made correctly.
- $result = implode('<br />', $result);
- if (preg_match('/Error/', $result)) {
- drupal_set_message('Unable to generate a BLAST database from your uploaded
- FASTA sequence. Please check that your file is a valid FASTA file and that if
- your sequence headers include pipes (i.e.: | ) they adhere to '
- . l('NCBI standards.', 'http://www.ncbi.nlm.nih.gov/books/NBK21097/table/A632/?report=objectonly', array('attributes' => array('target' => '_blank'))),
- 'error'
- );
- $error = TRUE;
- }
- }
- // 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.
- $advanced_options = array();
- $advanced_options_form_submit = 'blast_ui_' . $blast_program . '_advanced_options_form_submit';
- if (function_exists($advanced_options_form_submit)) {
- $advanced_options = call_user_func_array(
- $advanced_options_form_submit,
- array($form, &$form_state)
- );
- }
- else {
- $advanced_options = array('none' => 0);
- }
- // Set BLAST db paths
- if ($mdb_type == 'nucl' && preg_match('/\.[pn]al/', $blastdb_with_path) == 0) {
- $file_suffix = ".nsq";
- $blastdb_with_suffix = $blastdb_with_path . $file_suffix;
- }
- else if ($mdb_type == 'prot' && preg_match('/\.[pn]al/', $blastdb_with_path) == 0) {
- $file_suffix = ".psq";
- $blastdb_with_suffix = $blastdb_with_path . $file_suffix;
- }
- else {
- $blastdb_with_suffix = $blastdb_with_path;
- $blastdb_with_path= preg_replace('/\.[pn]al/', '', $blastdb_with_path);
- }
- // Actually submit the BLAST Tripal Job
- // NOTE: Tripal jobs need to be executed from the command-line before to run!!
- $blastdb_with_suffix = $blastdb_with_path . $file_suffix;
- if (is_readable($blastdb_with_suffix)) {
- global $user;
- $output_filestub = date('YMd_His');
- $job_args = array(
- 'program' => $blast_program,
- 'query' => $query,
- 'database' => $blastdb_with_path,
- 'output_filename' => $output_filestub,
- 'options' => $advanced_options
- );
- $job_id = tripal_add_job(
- t('BLAST (@program): @query', array('@program' => $blast_program, '@query' => $query)),
- 'blast_job',
- 'run_BLAST_tripal_job',
- $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[] = 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' => $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;
-
- 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';
- tripal_report_error(
- 'blast_ui',
- TRIPAL_ERROR,
- "BLAST database %db unaccessible. $dbfile_uploaded_msg",
- array('%db' => $blastdb_with_path)
- );
- drupal_set_message('BLAST database unaccessible. Please contact the site administrator.','error');
- }
- }
|