Tripal v1.0 (6.x-1.0)
|
00001 <?php 00002 00016 require_once "includes/tripal_feature.admin.inc"; 00017 require_once "includes/syncFeatures.inc"; 00018 require_once "includes/indexFeatures.inc"; 00019 require_once "includes/fasta_loader.inc"; 00020 require_once "includes/gff_loader.inc"; 00021 00022 require_once "api/tripal_feature.api.inc"; 00023 00024 require_once "includes/tripal_feature-delete.inc"; 00025 require_once "includes/tripal_feature-secondary_tables.inc"; 00026 require_once "includes/tripal_feature-properties.inc"; 00027 require_once "includes/tripal_feature-relationships.inc"; 00028 require_once "includes/tripal_feature-db_references.inc"; 00029 00030 00035 function tripal_feature_init() { 00036 00037 drupal_add_js(drupal_get_path('theme', 'tripal') . '/js/tripal_feature.js'); 00038 drupal_add_css(drupal_get_path('theme', 'tripal') . '/css/tripal_feature.css'); 00039 } 00040 00050 function tripal_feature_views_api() { 00051 return array( 00052 'api' => 2.0, 00053 ); 00054 } 00055 00069 function tripal_feature_help($path, $arg) { 00070 $output = ''; 00071 switch ($path) { 00072 case "admin/help#tripal_feature": 00073 $output='<p>' . t("Displays links to nodes created on this date") . '</p>'; 00074 break; 00075 } 00076 return $output; 00077 } 00078 00085 function tripal_feature_node_info() { 00086 $nodes = array(); 00087 00088 $nodes['chado_feature'] = array( 00089 'name' => t('Feature'), 00090 'module' => 'chado_feature', 00091 'description' => t('A feature from the chado database'), 00092 'has_title' => FALSE, 00093 'title_label' => t('Feature'), 00094 'has_body' => FALSE, 00095 'body_label' => t('Feature Description'), 00096 'locked' => TRUE 00097 ); 00098 return $nodes; 00099 } 00100 00108 function tripal_feature_perm() { 00109 return array( 00110 'access chado_feature content', 00111 'create chado_feature content', 00112 'delete chado_feature content', 00113 'edit chado_feature content', 00114 'administer tripal features', 00115 ); 00116 } 00117 00123 function chado_feature_access($op, $node, $account) { 00124 if ($op == 'create') { 00125 if (!user_access('create chado_feature content', $account)) { 00126 return FALSE; 00127 } 00128 } 00129 00130 if ($op == 'update') { 00131 if (!user_access('edit chado_feature content', $account)) { 00132 return FALSE; 00133 } 00134 } 00135 if ($op == 'delete') { 00136 if (!user_access('delete chado_feature content', $account)) { 00137 return FALSE; 00138 } 00139 } 00140 if ($op == 'view') { 00141 if (!user_access('access chado_feature content', $account)) { 00142 return FALSE; 00143 } 00144 } 00145 return NULL; 00146 } 00154 function tripal_feature_menu() { 00155 $items = array(); 00156 00157 // the administative settings menu 00158 $items['admin/tripal/tripal_feature'] = array( 00159 'title' => 'Features', 00160 'description' => 'Basic Description of Tripal Organism Module Functionality', 00161 'page callback' => 'theme', 00162 'page arguments' => array('tripal_feature_admin'), 00163 'access arguments' => array('administer tripal features'), 00164 'type' => MENU_NORMAL_ITEM, 00165 ); 00166 $items['admin/tripal/tripal_feature/configuration'] = array( 00167 'title' => 'Feature Configuration', 00168 'description' => 'Settings for Chado Features', 00169 'page callback' => 'drupal_get_form', 00170 'page arguments' => array('tripal_feature_admin'), 00171 'access arguments' => array('administer tripal features'), 00172 'type' => MENU_NORMAL_ITEM, 00173 ); 00174 $items['admin/tripal/tripal_feature/fasta_loader'] = array( 00175 'title' => 'Import a multi-FASTA file', 00176 'description' => 'Load sequences from a multi-FASTA file into Chado', 00177 'page callback' => 'drupal_get_form', 00178 'page arguments' => array('tripal_feature_fasta_load_form'), 00179 'access arguments' => array('administer tripal features'), 00180 'type' => MENU_NORMAL_ITEM, 00181 ); 00182 $items['admin/tripal/tripal_feature/gff3_load'] = array( 00183 'title' => 'Import a GFF3 file', 00184 'description' => 'Import a GFF3 file into Chado', 00185 'page callback' => 'drupal_get_form', 00186 'page arguments' => array('tripal_feature_gff3_load_form'), 00187 'access arguments' => array('administer tripal features'), 00188 'type' => MENU_NORMAL_ITEM, 00189 ); 00190 00191 $items['admin/tripal/tripal_feature/delete'] = array( 00192 'title' => ' Delete Features', 00193 'description' => 'Delete multiple features from Chado', 00194 'page callback' => 'drupal_get_form', 00195 'page arguments' => array('tripal_feature_delete_form'), 00196 'access arguments' => array('administer tripal features'), 00197 'type' => MENU_NORMAL_ITEM, 00198 ); 00199 00200 $items['admin/tripal/tripal_feature/sync'] = array( 00201 'title' => ' Sync Features', 00202 'description' => 'Sync features from Chado with Drupal', 00203 'page callback' => 'drupal_get_form', 00204 'page arguments' => array('tripal_feature_sync_form'), 00205 'access arguments' => array('administer tripal features'), 00206 'type' => MENU_NORMAL_ITEM, 00207 ); 00208 00209 // Adding Secondary Properties 00210 00240 //Edit/Deleting Secondary Properties------------- 00241 $items['node/%tf_node/edit_feature_properties'] = array( 00242 'title' => 'Edit Properties', 00243 'description' => 'Settings for Features', 00244 'page callback' => 'tripal_feature_edit_ALL_properties_page', 00245 'page arguments' => array(1), 00246 'access arguments' => array('edit chado_feature content'), 00247 'type' => MENU_LOCAL_TASK, 00248 'weight' => 8, 00249 ); 00261 $items['node/%tf_node/tf_edit_db_references'] = array( 00262 'title' => 'Edit References', 00263 'description' => 'Settings for Feature', 00264 'page callback' => 'tripal_feature_edit_ALL_dbreferences_page', 00265 'page arguments' => array(1), 00266 'access arguments' => array('edit chado_feature content'), 00267 'type' => MENU_LOCAL_TASK, 00268 'weight' => 10, 00269 ); 00270 00271 // the menu link for addressing any feature (by name, uniquename, synonym) 00272 $items['feature/%'] = array( 00273 'title' => 'Matched Features', 00274 'description' => 'Shows all features that match the provided ID. If multiple features match even by name, uniquename or synonym then a page is presented to allow the user to select which one they intended.', 00275 'page callback' => 'tripal_feature_match_features_page', 00276 'page arguments' => array(1), 00277 'access arguments' => array('access chado_feature content'), 00278 'type' => MENU_NORMAL_ITEM, 00279 ); 00280 00281 return $items; 00282 } 00283 00292 function tf_node_load($nid) { 00293 if (is_numeric($nid)) { 00294 $node = node_load($nid); 00295 if ($node->type == 'chado_feature') { 00296 return $node; 00297 } 00298 } 00299 return FALSE; 00300 } 00308 function tripal_feature_theme() { 00309 return array( 00310 'tripal_feature_search_index' => array( 00311 'arguments' => array('node'), 00312 ), 00313 'tripal_feature_search_results' => array( 00314 'arguments' => array('node'), 00315 ), 00316 'tripal_organism_feature_browser' => array( 00317 'arguments' => array('node' => NULL), 00318 'template' => 'tripal_organism_feature_browser', 00319 ), 00320 'tripal_organism_feature_counts' => array( 00321 'arguments' => array('node' => NULL), 00322 'template' => 'tripal_organism_feature_counts', 00323 ), 00324 'tripal_feature_base' => array( 00325 'arguments' => array('node' => NULL), 00326 'template' => 'tripal_feature_base', 00327 ), 00328 'tripal_feature_sequence' => array( 00329 'arguments' => array('node' => NULL), 00330 'template' => 'tripal_feature_sequence', 00331 ), 00332 'tripal_feature_synonyms' => array( 00333 'arguments' => array('node' => NULL), 00334 'template' => 'tripal_feature_synonyms', 00335 ), 00336 'tripal_feature_featureloc_sequences' => array( 00337 'arguments' => array('node' => NULL), 00338 'template' => 'tripal_feature_featureloc_sequences', 00339 ), 00340 'tripal_feature_references' => array( 00341 'arguments' => array('node' => NULL), 00342 'template' => 'tripal_feature_references', 00343 ), 00344 'tripal_feature_properties' => array( 00345 'arguments' => array('node' => NULL), 00346 'template' => 'tripal_feature_properties', 00347 ), 00348 'tripal_feature_terms' => array( 00349 'arguments' => array('node' => NULL), 00350 'template' => 'tripal_feature_terms', 00351 ), 00352 'tripal_feature_alignments' => array( 00353 'arguments' => array('node' => NULL), 00354 'template' => 'tripal_feature_alignments', 00355 ), 00356 'tripal_feature_relationships' => array( 00357 'arguments' => array('node' => NULL), 00358 'template' => 'tripal_feature_relationships', 00359 ), 00360 'tripal_feature_edit_ALL_properties_form' => array( 00361 'arguments' => array('form' => NULL), 00362 'function' => 'theme_tripal_feature_edit_ALL_properties_form', 00363 ), 00364 'tripal_feature_admin' => array( 00365 'template' => 'tripal_feature_admin', 00366 'arguments' => array(NULL), 00367 'path' => drupal_get_path('module', 'tripal_feature') . '/theme' 00368 ), 00369 ); 00370 } 00376 function tripal_feature_block($op = 'list', $delta = 0, $edit=array()) { 00377 switch ($op) { 00378 case 'list': 00379 $blocks['references']['info'] = t('Tripal Feature References'); 00380 $blocks['references']['cache'] = BLOCK_NO_CACHE; 00381 00382 $blocks['base']['info'] = t('Tripal Feature Details'); 00383 $blocks['base']['cache'] = BLOCK_NO_CACHE; 00384 00385 $blocks['sequence']['info'] = t('Tripal Feature Sequence'); 00386 $blocks['sequence']['cache'] = BLOCK_NO_CACHE; 00387 00388 $blocks['featureloc_sequences']['info'] = t('Tripal Feature Annotated Sequence'); 00389 $blocks['featureloc_sequences']['cache'] = BLOCK_NO_CACHE; 00390 00391 $blocks['synonyms']['info'] = t('Tripal Feature Synonyms'); 00392 $blocks['synonyms']['cache'] = BLOCK_NO_CACHE; 00393 00394 $blocks['properties']['info'] = t('Tripal Feature Properties'); 00395 $blocks['properties']['cache'] = BLOCK_NO_CACHE;; 00396 00397 $blocks['terms']['info'] = t('Tripal Annotated Terms'); 00398 $blocks['terms']['cache'] = BLOCK_NO_CACHE;; 00399 00400 $blocks['alignments']['info'] = t('Tripal Feature Alignments'); 00401 $blocks['alignments']['cache'] = BLOCK_NO_CACHE; 00402 00403 $blocks['relationships']['info'] = t('Tripal Feature Relationships'); 00404 $blocks['relationships']['cache'] = BLOCK_NO_CACHE; 00405 00406 $blocks['org_feature_counts']['info'] = t('Tripal Organism Feature Counts'); 00407 $blocks['org_feature_counts']['cache'] = BLOCK_NO_CACHE; 00408 00409 $blocks['org_feature_browser']['info'] = t('Tripal Organism Feature Browser'); 00410 $blocks['org_feature_browser']['cache'] = BLOCK_NO_CACHE; 00411 00412 return $blocks; 00413 00414 case 'view': 00415 if (user_access('access chado_feature content') and arg(0) == 'node' and is_numeric(arg(1))) { 00416 $nid = arg(1); 00417 $node = node_load($nid); 00418 00419 $block = array(); 00420 switch ($delta) { 00421 case 'references': 00422 $block['subject'] = t('References'); 00423 $block['content'] = theme('tripal_feature_references', $node); 00424 break; 00425 case 'base': 00426 $block['subject'] = t('Feature Details'); 00427 $block['content'] = theme('tripal_feature_base', $node); 00428 break; 00429 case 'synonyms': 00430 $block['subject'] = t('Synonyms'); 00431 $block['content'] = theme('tripal_feature_synonyms', $node); 00432 break; 00433 case 'properties': 00434 $block['subject'] = t('Properties'); 00435 $block['content'] = theme('tripal_feature_properties', $node); 00436 break; 00437 case 'terms': 00438 $block['subject'] = t('Annotated Terms'); 00439 $block['content'] = theme('tripal_feature_terms', $node); 00440 break; 00441 case 'sequence': 00442 $block['subject'] = t('Sequence'); 00443 $block['content'] = theme('tripal_feature_sequence', $node); 00444 break; 00445 case 'featureloc_sequences': 00446 $block['subject'] = t('Formatted Sequences'); 00447 $block['content'] = theme('tripal_feature_featureloc_sequences', $node); 00448 break; 00449 case 'alignments': 00450 $block['subject'] = t('Alignments'); 00451 $block['content'] = theme('tripal_feature_alignments', $node); 00452 break; 00453 case 'relationships': 00454 $block['subject'] = t('Relationships'); 00455 $block['content'] = theme('tripal_feature_relationships', $node); 00456 break; 00457 case 'org_feature_counts': 00458 $block['subject'] = t('Feature Type Summary'); 00459 $block['content'] = theme('tripal_organism_feature_counts', $node); 00460 break; 00461 case 'org_feature_browser': 00462 $block['subject'] = t('Feature Browser'); 00463 $block['content'] = theme('tripal_organism_feature_browser', $node); 00464 break; 00465 case 'library_feature_browser': 00466 $block['subject'] = t('Library Feature Browser'); 00467 $block['content'] = theme('tripal_library_feature_browser', $node); 00468 break; 00469 case 'analysis_feature_browser': 00470 $block['subject'] = t('Analysis Feature Browser'); 00471 $block['content'] = theme('tripal_analysis_feature_browser', $node); 00472 break; 00473 default : 00474 } 00475 return $block; 00476 } 00477 00478 } 00479 } 00487 function chado_feature_insert($node) { 00488 // remove spaces, newlines from residues 00489 $residues = preg_replace("/[\n\r\s]/", "", $node->residues); 00490 $obsolete = 'FALSE'; 00491 if ($node->is_obsolete) { 00492 $obsolete = 'TRUE'; 00493 } 00494 00495 // check to see if we are inserting a duplicate record. 00496 $values = array( 00497 'cv_id' => array( 00498 'name' => 'sequence' 00499 ), 00500 'name' => $node->feature_type 00501 ); 00502 $type = tripal_core_chado_select('cvterm', array('cvterm_id'), $values); 00503 $values = array( 00504 'organism_id' => $node->organism_id, 00505 'name' => $node->fname, 00506 'uniquename' => $node->uniquename, 00507 'residues' => $residues, 00508 'seqlen' => drupal_strlen($residues), 00509 'is_obsolete' => $obsolete, 00510 'type_id' => $type[0]->cvterm_id, 00511 'md5checksum' => md5($residues) 00512 ); 00513 $options = array('is_duplicate' => TRUE, 'has_record' => TRUE); 00514 $exists = tripal_core_chado_select('feature', array('*'), $values, $options); 00515 00516 // if the record is not a duplicate then add it 00517 if (!$exists) { 00518 $istatus = tripal_core_chado_insert('feature', $values); 00519 if (!$istatus) { 00520 drupal_set_message(t('Unable to add feature.'), 'warning'); 00521 watchdog('tripal_feature', 'Insert feature: Unable to create feature where values: %values', 00522 array('%values' => print_r($values, TRUE)), WATCHDOG_WARNING); 00523 } 00524 } 00525 00526 // now get the newly added record 00527 $values = array( 00528 'organism_id' => $node->organism_id, 00529 'uniquename' => $node->uniquename, 00530 'type_id' => $type[0]->cvterm_id, 00531 ); 00532 $feature = tripal_core_chado_select('feature', array('feature_id'), $values); 00533 00534 // add the genbank accession and synonyms 00535 chado_feature_add_synonyms($node->synonyms, $feature[0]->feature_id); 00536 00537 // make sure the entry for this feature doesn't already exist in the chado_feature table 00538 // if it doesn't exist then we want to add it. 00539 $node_check_sql = "SELECT * FROM {chado_feature} " . 00540 "WHERE feature_id = '%s'"; 00541 $node_check = db_fetch_object(db_query($node_check_sql, $feature[0]->feature_id)); 00542 if (!$node_check) { 00543 // next add the item to the drupal table 00544 $sql = "INSERT INTO {chado_feature} (nid, vid, feature_id, sync_date) ". 00545 "VALUES (%d, %d, %d, " . time() . ")"; 00546 db_query($sql, $node->nid, $node->vid, $feature[0]->feature_id); 00547 } 00548 } 00549 00555 function chado_feature_update($node) { 00556 if ($node->revision) { 00557 // there is no way to handle revisions in Chado but leave 00558 // this here just to make not we've addressed it. 00559 } 00560 00561 $residues = preg_replace("/[\n\r\s]/", "", $node->residues); 00562 $obsolete = 'FALSE'; 00563 if ($node->is_obsolete) { 00564 $obsolete = 'TRUE'; 00565 } 00566 00567 // get the feature type id 00568 $values = array( 00569 'cv_id' => array( 00570 'name' => 'sequence' 00571 ), 00572 'name' => $node->feature_type 00573 ); 00574 $type = tripal_core_chado_select('cvterm', array('cvterm_id'), $values); 00575 00576 $feature_id = chado_get_id_for_node('feature', $node) ; 00577 00578 if (sizeof($type) > 0) { 00579 $match = array( 00580 'feature_id' => $feature_id, 00581 ); 00582 $values = array( 00583 'organism_id' => $node->organism_id, 00584 'name' => $node->fname, 00585 'uniquename' => $node->uniquename, 00586 'residues' => $residues, 00587 'seqlen' => drupal_strlen($residues), 00588 'is_obsolete' => $obsolete, 00589 'type_id' => $type[0]->cvterm_id, 00590 'md5checksum' => md5($residues) 00591 ); 00592 $options = array('return_record' => TRUE); 00593 $status = tripal_core_chado_update('feature', $match, $values, $options); 00594 00595 // add the genbank synonyms 00596 chado_feature_add_synonyms($node->synonyms, $feature_id); 00597 } 00598 else { 00599 drupal_set_message(t('Unable to update feature.'), 'warning'); 00600 watchdog('tripal_feature', 00601 'Update feature: Unable to update feature where values: %values', 00602 array('%values' => print_r($values, TRUE)), 00603 WATCHDOG_WARNING 00604 ); 00605 } 00606 } 00612 function chado_feature_delete($node) { 00613 00614 $feature_id = chado_get_id_for_node('feature', $node); 00615 00616 // if we don't have a library id for this node then this isn't a node of 00617 // type chado_library or the entry in the chado_library table was lost. 00618 if (!$feature_id) { 00619 return; 00620 } 00621 00622 // remove the drupal content 00623 $sql_del = "DELETE FROM {chado_feature} ". 00624 "WHERE nid = %d ". 00625 "AND vid = %d"; 00626 db_query($sql_del, $node->nid, $node->vid); 00627 $sql_del = "DELETE FROM {node} ". 00628 "WHERE nid = %d ". 00629 "AND vid = %d"; 00630 db_query($sql_del, $node->nid, $node->vid); 00631 $sql_del = "DELETE FROM {node_revisions} ". 00632 "WHERE nid = %d ". 00633 "AND vid = %d"; 00634 db_query($sql_del, $node->nid, $node->vid); 00635 00636 00637 // Remove data from feature tables of chado database. This will 00638 // cause a cascade delete and remove all data in referencing tables 00639 // for this feature 00640 chado_query("DELETE FROM {feature} WHERE feature_id = %d", $feature_id); 00641 00642 drupal_set_message(t("The feature and all associated data were removed from") . 00643 "chado"); 00644 00645 } 00651 function chado_feature_add_synonyms($synonyms, $feature_id) { 00652 00653 // make sure we only have a single space between each synonym 00654 $synonyms = preg_replace("/[\s\n\r]+/", " ", $synonyms); 00655 // split the synonyms into an array based on a space as the delimieter 00656 $syn_array = array(); 00657 $syn_array = explode(" ", $synonyms); 00658 00659 00660 // remove any old synonyms 00661 $feature_syn_dsql = "DELETE FROM {feature_synonym} WHERE feature_id = %d"; 00662 if (!chado_query($feature_syn_dsql, $feature_id)) { 00663 $error .= "Could not remove synonyms from feature. "; 00664 } 00665 00666 // return if we don't have any synonmys to add 00667 if (!$synonyms) { 00668 return; 00669 } 00670 // iterate through each synonym and add it to the database 00671 foreach ($syn_array as $syn) { 00672 // skip this item if it's empty 00673 if (!$syn) { 00674 break; } 00675 00676 // check to see if we have this accession number already in the database 00677 // if so then don't add it again. it messes up drupal if the insert fails. 00678 // It is possible for the accession number to be present and not the feature 00679 $synonym_sql = "SELECT synonym_id FROM {synonym} ". 00680 "WHERE name = '%s'"; 00681 $synonym = db_fetch_object(chado_query($synonym_sql, $syn)); 00682 if (!$synonym) { 00683 $synonym_isql = "INSERT INTO {synonym} (name,synonym_sgml,type_id) ". 00684 "VALUES ('%s','%s', ". 00685 " (SELECT cvterm_id ". 00686 " FROM {CVTerm} CVT ". 00687 " INNER JOIN CV ON CVT.cv_id = CV.cv_id ". 00688 " WHERE CV.name = 'feature_property' and CVT.name = 'synonym'))"; 00689 if (!chado_query($synonym_isql, $syn, $syn)) { 00690 $error .= "Could not add synonym. "; 00691 } 00692 // now get the synonym we just added 00693 $synonym_sql = "SELECT synonym_id FROM {synonym} ". 00694 "WHERE name = '%s'"; 00695 $synonym = db_fetch_object(chado_query($synonym_sql, $syn)); 00696 } 00697 00698 // now add in our new sysnonym 00699 $feature_syn_isql = "INSERT INTO {feature_synonym} (synonym_id,feature_id,pub_id) ". 00700 "VALUES (%d,%d,1)"; 00701 if (!chado_query($feature_syn_isql, $synonym->synonym_id, $feature_id)) { 00702 $error .= "Could not add synonyms to feature. "; 00703 } 00704 } 00705 00706 // return to the drupal database 00707 return $error; 00708 00709 } 00715 function chado_feature_add_gbaccession($accession, $feature_id) { 00716 00717 // use chado database 00718 00719 // remove any old accession from genbank dbEST 00720 $fdbxref_dsql = "DELETE FROM {feature_dbxref} ". 00721 "WHERE feature_id = %d and dbxref_id IN ". 00722 " (SELECT DBX.dbxref_id FROM {dbxref} DBX ". 00723 " INNER JOIN DB ON DB.db_id = DBX.db_id ". 00724 " INNER JOIN feature_dbxref FDBX ON DBX.dbxref_id = FDBX.dbxref_id ". 00725 " WHERE DB.name = 'DB:Genbank' and FDBX.feature_id = %d)"; 00726 if (!chado_query($fdbxref_dsql, $feature_id, $feature_id)) { 00727 $error .= "Could not remove accession from feature. "; 00728 } 00729 00730 // if we don't have an accession number to add then just return 00731 if (!$accession) { 00732 return; 00733 } 00734 // get the db_id 00735 $db_sql = "SELECT db_id FROM {DB} ". 00736 "WHERE name = 'DB:Genbank_est'"; 00737 $db = db_fetch_object(chado_query($db_sql)); 00738 00739 // check to see if we have this accession number already in the database 00740 // if so then don't add it again. it messes up drupal if the insert fails. 00741 // It is possible for the accession number to be present and not the feature 00742 $dbxref_sql = "SELECT dbxref_id FROM {dbxref} ". 00743 "WHERE db_id = %d and accession = '%s'"; 00744 $dbxref = db_fetch_object(chado_query($dbxref_sql, $db->db_id, $accession)); 00745 if (!$dbxref) { 00746 // add the accession number 00747 $dbxref_isql = "INSERT INTO {dbxref} (db_id,accession) ". 00748 " VALUES (%d, '%s') "; 00749 if (!chado_query($dbxref_isql, $db->db_id, $accession)) { 00750 $error .= 'Could not add accession as a database reference '; 00751 } 00752 // get the dbxref_id for the just added accession number 00753 $dbxref_sql = "SELECT dbxref_id FROM {dbxref} ". 00754 "WHERE db_id = %d and accession = '%s'"; 00755 $dbxref = db_fetch_object(chado_query($dbxref_sql, $db->db_id, $accession)); 00756 } 00757 00758 00759 // associate the accession number with the feature 00760 $feature_dbxref_isql = "INSERT INTO {feature_dbxref} (feature_id,dbxref_id) ". 00761 " VALUES (%d, %d) "; 00762 if (!chado_query($feature_dbxref_isql, $feature_id, $dbxref->dbxref_id)) { 00763 $error .= 'Could not add feature database reference. '; 00764 } 00765 00766 return $error; 00767 } 00768 00774 function chado_feature_form($node, $param) { 00775 00776 $type = node_get_types('type', $node); 00777 $form = array(); 00778 00779 $feature = $node->feature; 00780 00781 // add the residues to the feature object 00782 $feature = tripal_core_expand_chado_vars($feature, 'field', 'feature.residues'); 00783 00784 // if the node has synonyms then use that as the form may be returning 00785 // from an error. Otherwise try to find synonyms from the database 00786 $synonyms = $node->synonyms; 00787 $feature = tripal_core_expand_chado_vars($feature, 'table', 'feature_synonym'); 00788 $feature_synonyms = $feature->feature_synonym; 00789 if (!$synonyms) { 00790 if (!is_array($feature_synonyms)) { 00791 $synonyms = $feature_synonyms->synonym_id->name; 00792 } 00793 elseif (is_array($feature_synonyms)) { 00794 foreach ($feature_synonyms as $index => $synonym) { 00795 $synonyms .= $synonym->synonym_id->name . "\n"; 00796 } 00797 } 00798 } 00799 00800 $analyses = $node->analyses; 00801 $references = $node->references; 00802 00803 // We need to pass above variables for preview to show 00804 $form['feature'] = array( 00805 '#type' => 'value', 00806 '#value' => $feature 00807 ); 00808 // This field is read when previewing a node 00809 $form['synonyms'] = array( 00810 '#type' => 'value', 00811 '#value' => $synonyms 00812 ); 00813 // This field is read when previewing a node 00814 $form['analyses'] = array( 00815 '#type' => 'value', 00816 '#value' => $analyses 00817 ); 00818 // This field is read when previewing a node 00819 $form['references'] = array( 00820 '#type' => 'value', 00821 '#value' => $references 00822 ); 00823 00824 // keep track of the feature id if we have one. If we do have one then 00825 // this would indicate an update as opposed to an insert. 00826 $form['feature_id'] = array( 00827 '#type' => 'value', 00828 '#value' => $feature->feature_id, 00829 ); 00830 00831 $form['title']= array( 00832 '#type' => 'textfield', 00833 '#title' => t('Title'), 00834 '#required' => TRUE, 00835 '#default_value' => $node->title, 00836 '#description' => t('The title must be a unique identifier for this feature. It is recommended to use a combination of uniquename, organism and feature type in the title as this is guranteed to be unique.'), 00837 '#weight' => 1, 00838 '#maxlength' => 255 00839 ); 00840 00841 $form['uniquename']= array( 00842 '#type' => 'textfield', 00843 '#title' => t('Unique Feature Name'), 00844 '#required' => TRUE, 00845 '#default_value' => $feature->uniquename, 00846 '#description' => t('Enter a unique name for this feature. This name must be unique for the organism and feature type.'), 00847 '#weight' => 1, 00848 '#maxlength' => 255 00849 ); 00850 00851 $form['fname']= array( 00852 '#type' => 'textfield', 00853 '#title' => t('Feature Name'), 00854 '#required' => TRUE, 00855 '#default_value' => $feature->name, 00856 '#description' => t('Enter the name used by humans to refer to this feature.'), 00857 '#weight' => 1, 00858 '#maxlength' => 255 00859 ); 00860 00861 // get the list of supported feature types 00862 $ftypes = array(); 00863 $ftypes[''] = ''; 00864 $supported_ftypes = split("[ \n]", variable_get('tripal_feature_type_setting', 'gene mRNA EST contig')); 00865 foreach ($supported_ftypes as $ftype) { 00866 $ftypes["$ftype"] = $ftype; 00867 } 00868 00869 $form['feature_type'] = array( 00870 '#title' => t('Feature Type'), 00871 '#type' => t('select'), 00872 '#description' => t("Choose the feature type."), 00873 '#required' => TRUE, 00874 '#default_value' => $feature->type_id->name, 00875 '#options' => $ftypes, 00876 '#weight' => 2 00877 ); 00878 00879 // get the list of organisms 00880 $sql = "SELECT * FROM {Organism} ORDER BY genus, species"; 00881 $org_rset = chado_query($sql); 00882 $organisms = array(); 00883 $organisms[''] = ''; 00884 while ($organism = db_fetch_object($org_rset)) { 00885 $organisms[$organism->organism_id] = "$organism->genus $organism->species ($organism->common_name)"; 00886 } 00887 $form['organism_id'] = array( 00888 '#title' => t('Organism'), 00889 '#type' => t('select'), 00890 '#description' => t("Choose the organism with which this feature is associated"), 00891 '#required' => TRUE, 00892 '#default_value' => $feature->organism_id->organism_id, 00893 '#options' => $organisms, 00894 '#weight' => 3, 00895 ); 00896 00897 // Get synonyms 00898 if ($synonyms) { 00899 if (is_array($synonyms)) { 00900 foreach ($synonyms as $synonym) { 00901 $syn_text .= "$synonym->name\n"; 00902 } 00903 } 00904 else { 00905 $syn_text = $synonyms; 00906 } 00907 } 00908 $form['synonyms']= array( 00909 '#type' => 'textarea', 00910 '#title' => t('Synonyms'), 00911 '#required' => FALSE, 00912 '#default_value' => $syn_text, 00913 '#description' => t('Enter alternate names (synonmys) for this feature to help in searching and identification. You may enter as many alternate names as needed separated by spaces or on different lines.'), 00914 '#weight' => 5, 00915 ); 00916 00917 $form['residues']= array( 00918 '#type' => 'textarea', 00919 '#title' => t('Residues'), 00920 '#required' => FALSE, 00921 '#default_value' => $feature->residues, 00922 '#description' => t('Enter the nucelotide sequences for this feature'), 00923 '#weight' => 6 00924 ); 00925 00926 $checked = ''; 00927 if ($feature->is_obsolete == 't') { 00928 $checked = '1'; 00929 } 00930 $form['is_obsolete']= array( 00931 '#type' => 'checkbox', 00932 '#title' => t('Is Obsolete'), 00933 '#required' => FALSE, 00934 '#default_value' => $checked, 00935 '#description' => t('Check this box if this sequence should be retired and no longer included in further analysis.'), 00936 '#weight' => 8 00937 ); 00938 return $form; 00939 } 00945 function chado_feature_validate($node) { 00946 $result = 0; 00947 00948 // if this is an update, we want to make sure that a different feature for 00949 // the organism doesn't already have this uniquename. We don't want to give 00950 // two sequences the same uniquename 00951 if ($node->feature_id) { 00952 $sql = "SELECT * 00953 FROM {Feature} F 00954 INNER JOIN {cvterm} CVT ON F.type_id = CVT.cvterm_id 00955 WHERE uniquename = '%s' 00956 AND organism_id = %d AND CVT.name = '%s' AND NOT feature_id = %d"; 00957 $result = db_fetch_object(chado_query($sql, $node->uniquename, $node->organism_id, $node->feature_type, $node->feature_id)); 00958 if ($result) { 00959 form_set_error('uniquename', t("Feature update cannot proceed. The feature name '$node->uniquename' is not unique for this organism. Please provide a unique name for this feature.")); 00960 } 00961 } 00962 00963 // if this is an insert then we just need to make sure this name doesn't 00964 // already exist for this organism if it does then we need to throw an error 00965 else { 00966 $sql = "SELECT * 00967 FROM {Feature} F 00968 INNER JOIN {cvterm} CVT ON F.type_id = CVT.cvterm_id 00969 WHERE uniquename = '%s' 00970 AND organism_id = %d AND CVT.name = '%s'"; 00971 $result = db_fetch_object(chado_query($sql, $node->uniquename, $node->organism_id, $node->feature_type)); 00972 if ($result) { 00973 form_set_error('uniquename', t("Feature insert cannot proceed. The feature name '$node->uniquename' already exists for this organism. Please provide a unique name for this feature.")); 00974 } 00975 } 00976 00977 // we don't allow a genbank accession number for a contig 00978 if ($node->feature_type == 'contig' and $node->gbaccession) { 00979 form_set_error('gbaccession', t("Contigs cannot have a genbank accession number. Please change the feature type or remove the accession number")); 00980 } 00981 00982 } 00989 function chado_feature_load($node) { 00990 00991 // get the feature details from chado 00992 $feature_id = chado_get_id_for_node('feature', $node); 00993 00994 $values = array('feature_id' => $feature_id); 00995 $feature = tripal_core_generate_chado_var('feature', $values); 00996 00997 if (strcmp($feature->name, $feature->uniquename)==0) { 00998 $node->title = $feature->name . " (" . $feature->type_id->name . ") " . $feature->organism_id->genus . " " . $feature->organism_id->species ; 00999 } 01000 01001 $additions = new stdClass(); 01002 $additions->feature = $feature; 01003 return $additions; 01004 } 01010 function tripal_feature_load_organism($organism_id) { 01011 // add organism details 01012 $sql = "SELECT * FROM {organism} WHERE organism_id = %d"; 01013 $organism = db_fetch_object(chado_query($sql, $organism_id)); 01014 return $organism; 01015 } 01021 function tripal_feature_load_synonyms($feature_id) { 01022 01023 $sql = "SELECT S.name ". 01024 "FROM {Feature_Synonym} FS ". 01025 " INNER JOIN {Synonym} S ". 01026 " ON FS.synonym_id = S.Synonym_id ". 01027 "WHERE FS.feature_id = %d ". 01028 "ORDER BY S.name "; 01029 $results = chado_query($sql, $feature_id); 01030 $synonyms = array(); 01031 $i=0; 01032 while ($synonym = db_fetch_object($results)) { 01033 $synonyms[$i++] = $synonym; 01034 } 01035 return $synonyms; 01036 } 01042 function tripal_feature_load_properties($feature_id) { 01043 01044 $sql = "SELECT CVT.name as cvname, FS.type_id, FS.value, FS.rank, 01045 CVT.definition, CVT.is_obsolete, 01046 DBX.dbxref_id,DBX.accession,DB.name as dbname, 01047 DB.urlprefix, DB.description as db_description, DB.url 01048 FROM {featureprop} FS 01049 INNER JOIN {cvterm} CVT ON FS.type_id = CVT.cvterm_id 01050 INNER JOIN {dbxref} DBX ON CVT.dbxref_id = DBX.dbxref_id 01051 INNER JOIN {db} DB ON DB.db_id = DBX.db_id 01052 WHERE FS.feature_id = %d 01053 ORDER BY FS.rank ASC"; 01054 $results = chado_query($sql, $feature_id); 01055 $i=0; 01056 $properties = array(); 01057 while ($property = db_fetch_object($results)) { 01058 $properties[$i++] = $property; 01059 } 01060 return $properties; 01061 } 01067 function tripal_feature_load_references($feature_id) { 01068 01069 $sql = "SELECT F.uniquename,F.Feature_id,DBX.accession,DB.description as dbdesc, ". 01070 " DB.db_id, DB.name as db_name, DB.urlprefix,DBX.dbxref_id ". 01071 "FROM {feature} F ". 01072 " INNER JOIN {feature_dbxref} FDBX on F.feature_id = FDBX.feature_id ". 01073 " INNER JOIN {dbxref} DBX on DBX.dbxref_id = FDBX.dbxref_id ". 01074 " INNER JOIN {db} on DB.db_id = DBX.db_id ". 01075 "WHERE F.feature_id = %d ". 01076 "ORDER BY DB.name "; 01077 $results = chado_query($sql, $feature_id); 01078 $references = array(); 01079 $i=0; 01080 while ($accession = db_fetch_object($results)) { 01081 $references[$i++] = $accession; 01082 } 01083 return $references; 01084 } 01090 function tripal_feature_load_featurelocs($feature_id, $side = 'as_parent', $aggregate = 1) { 01091 01092 $sql = "SELECT 01093 F.name, F.feature_id, F.uniquename, 01094 FS.name as src_name, 01095 FS.feature_id as src_feature_id, 01096 FS.uniquename as src_uniquename, 01097 CVT.name as cvname, CVT.cvterm_id, 01098 CVTS.name as src_cvname, CVTS.cvterm_id as src_cvterm_id, 01099 FL.fmin, FL.fmax, FL.is_fmin_partial, FL.is_fmax_partial,FL.strand, 01100 FL.phase 01101 FROM {featureloc} FL 01102 INNER JOIN {feature} F on FL.feature_id = F.feature_id 01103 INNER JOIN {feature} FS on FS.feature_id = FL.srcfeature_id 01104 INNER JOIN {cvterm} CVT on F.type_id = CVT.cvterm_id 01105 INNER JOIN {cvterm} CVTS on FS.type_id = CVTS.cvterm_id 01106 "; 01107 if (strcmp($side, 'as_parent')==0) { 01108 $sql .= "WHERE FL.srcfeature_id = %d "; 01109 } 01110 if (strcmp($side, 'as_child')==0) { 01111 $sql .= "WHERE FL.feature_id = %d "; 01112 } 01113 01114 $flresults = chado_query($sql, $feature_id); 01115 01116 // copy the results into an array 01117 $i=0; 01118 $featurelocs = array(); 01119 while ($loc = db_fetch_object($flresults)) { 01120 // if a drupal node exists for this feature then add the nid to the 01121 // results object 01122 $sql = 'SELECT nid FROM {chado_feature} WHERE feature_id = %d'; 01123 01124 $ffeature = db_fetch_object(db_query($sql, $loc->feature_id)); 01125 $sfeature = db_fetch_object(db_query($sql, $loc->src_feature_id)); 01126 $loc->fnid = $ffeature->nid; 01127 $loc->snid = $sfeature->nid; 01128 // add the result to the array 01129 $featurelocs[$i++] = $loc; 01130 } 01131 01132 // Add the relationship feature locs if aggregate is turned on 01133 if ($aggregate and strcmp($side, 'as_parent')==0) { 01134 // get the relationships for this feature without substituting any children 01135 // for the parent. We want all relationships 01136 $relationships = tripal_feature_get_aggregate_relationships($feature_id, 0); 01137 foreach ($relationships as $rindex => $rel) { 01138 // get the featurelocs for each of the relationship features 01139 $rel_featurelocs = tripal_feature_load_featurelocs($rel->subject_id, 'as_child', 0); 01140 foreach ($rel_featurelocs as $findex => $rfloc) { 01141 $featurelocs[$i++] = $rfloc; 01142 } 01143 } 01144 } 01145 01146 usort($featurelocs, 'tripal_feature_sort_locations'); 01147 return $featurelocs; 01148 } 01154 function tripal_feature_sort_locations($a, $b) { 01155 return strnatcmp($a->fmin, $b->fmin); 01156 } 01162 function tripal_feature_load_relationships($feature_id, $side = 'as_subject') { 01163 // get the relationships for this feature. The query below is used for both 01164 // querying the object and subject relationships 01165 $sql = "SELECT 01166 FS.name as subject_name, 01167 FS.uniquename as subject_uniquename, 01168 CVTS.name as subject_type, 01169 CVTS.cvterm_id as subject_type_id, 01170 FR.subject_id, 01171 FR.type_id as relationship_type_id, 01172 CVT.name as rel_type, 01173 FO.name as object_name, 01174 FO.uniquename as object_uniquename, 01175 CVTO.name as object_type, 01176 CVTO.cvterm_id as object_type_id, 01177 FR.object_id, 01178 FR.rank 01179 FROM {feature_relationship} FR 01180 INNER JOIN {cvterm} CVT ON FR.type_id = CVT.cvterm_id 01181 INNER JOIN {feature} FS ON FS.feature_id = FR.subject_id 01182 INNER JOIN {feature} FO ON FO.feature_id = FR.object_id 01183 INNER JOIN {cvterm} CVTO ON FO.type_id = CVTO.cvterm_id 01184 INNER JOIN {cvterm} CVTS ON FS.type_id = CVTS.cvterm_id 01185 "; 01186 if (strcmp($side, 'as_object')==0) { 01187 $sql .= " WHERE FR.object_id = %d"; 01188 } 01189 if (strcmp($side, 'as_subject')==0) { 01190 $sql .= " WHERE FR.subject_id = %d"; 01191 } 01192 $sql .= " ORDER BY FR.rank"; 01193 01194 // get the relationships 01195 $results = chado_query($sql, $feature_id); 01196 01197 01198 // iterate through the relationships, put these in an array and add 01199 // in the Drupal node id if one exists 01200 $i=0; 01201 $nodesql = "SELECT nid FROM {chado_feature} WHERE feature_id = %d"; 01202 $relationships = array(); 01203 while ($rel = db_fetch_object($results)) { 01204 $node = db_fetch_object(db_query($nodesql, $rel->subject_id)); 01205 if ($node) { 01206 $rel->subject_nid = $node->nid; 01207 } 01208 $node = db_fetch_object(db_query($nodesql, $rel->object_id)); 01209 if ($node) { 01210 $rel->object_nid = $node->nid; 01211 } 01212 $relationships[$i++] = $rel; 01213 } 01214 return $relationships; 01215 } 01221 function tripal_feature_get_aggregate_relationships($feature_id, $substitute=1, 01222 $levels=0, $base_type_id=NULL, $depth=0) { 01223 01224 // we only want to recurse to as many levels deep as indicated by the 01225 // $levels variable, but only if this variable is > 0. If 0 then we 01226 // recurse until we reach the end of the relationships tree. 01227 if ($levels > 0 and $levels == $depth) { 01228 return NULL; 01229 } 01230 01231 // first get the relationships for this feature 01232 $relationships = tripal_feature_load_relationships($feature_id, 'as_object'); 01233 01234 // next, iterate through these relationships and descend, adding in those 01235 // that are specified by the aggregator. 01236 $i=0; 01237 $new_relationships = array(); 01238 foreach ($relationships as $rindex => $rel) { 01239 // set the base type id 01240 if (!$base_type_id) { 01241 $base_type_id = $rel->object_type_id; 01242 } 01243 // check to see if we have an aggregator for this base type 01244 $sql = "SELECT * FROM {tripal_feature_relagg} WHERE type_id = %d and rel_type_id = %d"; 01245 $agg = db_fetch_object(db_query($sql, $base_type_id, $rel->subject_type_id)); 01246 if ($agg) { 01247 // if we're not going to substitute the resulting relationships for the 01248 // parent then we need to add the parent to our list 01249 if (!$substitute) { 01250 $new_relationships[$i++] = $rel; 01251 } 01252 // recurse all relationships 01253 $agg_relationships = tripal_feature_get_aggregate_relationships( 01254 $rel->subject_id, $levels, $base_type_id, $depth++); 01255 // if we have an aggregate defined but we have no relationships beyond 01256 // this point then there's nothing we can substitute 01257 if (!$agg_relationships and $substitute) { 01258 $new_relationships[$i++] = $rel; 01259 } 01260 01261 // merge all relationships into one array 01262 foreach ($agg_relationships as $aindex => $arel) { 01263 $new_relationships[$i++] = $arel; 01264 } 01265 } 01266 else { 01267 // if we don't have an aggregate then keep the current relationship 01268 $new_relationships[$i++] = $rel; 01269 } 01270 } 01271 return $new_relationships; 01272 } 01278 function tripal_feature_load_featureloc_sequences($feature_id, $featurelocs) { 01279 01280 // if we don't have any featurelocs then no point in continuing 01281 if (!$featurelocs) { 01282 return array(); 01283 } 01284 01285 // get the list of relationships (including any aggregators) and iterate 01286 // through each one to find information needed to color-code the reference sequence 01287 $relationships = tripal_feature_get_aggregate_relationships($feature_id); 01288 if (!$relationships) { 01289 return array(); 01290 } 01291 01292 01293 // iterate through each of the realtionships features and get their 01294 // locations 01295 foreach ($relationships as $rindex => $rel) { 01296 // get the featurelocs for each of the relationship features 01297 $rel_featurelocs = tripal_feature_load_featurelocs($rel->subject_id, 'as_child', 0); 01298 foreach ($rel_featurelocs as $rfindex => $rel_featureloc) { 01299 // keep track of this unique source feature 01300 $src = $rel_featureloc->src_feature_id ."-". $rel_featureloc->src_cvterm_id; 01301 01302 // copy over the results to the relationship object. Since there can 01303 // be more than one feature location for each relationship feature we 01304 // use the '$src' variable to keep track of these. 01305 $rel->featurelocs->$src->src_uniquename = $rel_featureloc->src_uniquename; 01306 $rel->featurelocs->$src->src_cvterm_id = $rel_featureloc->src_cvterm_id; 01307 $rel->featurelocs->$src->src_cvname = $rel_featureloc->src_cvname; 01308 $rel->featurelocs->$src->fmin = $rel_featureloc->fmin; 01309 $rel->featurelocs->$src->fmax = $rel_featureloc->fmax; 01310 $rel->featurelocs->$src->src_name = $rel_featureloc->src_name; 01311 01312 // keep track of the individual parts for each relationship 01313 $start = $rel->featurelocs->$src->fmin; 01314 $end = $rel->featurelocs->$src->fmax; 01315 $type = $rel->subject_type; 01316 $rel_locs[$src]['parts'][$start][$type]['start'] = $start; 01317 $rel_locs[$src]['parts'][$start][$type]['end'] = $end; 01318 $rel_locs[$src]['parts'][$start][$type]['type'] = $type; 01319 } 01320 } 01321 01322 // the featurelocs array provided to the function contains the locations 01323 // where this feature is found. We want to get the sequence for each 01324 // location and then annotate it with the parts found from the relationships 01325 // locations determiend above. 01326 $sql = "SELECT substring(residues from %d for %d) as residues ". 01327 "FROM {feature} ". 01328 "WHERE feature_id = %d"; 01329 $floc_sequences = array(); 01330 foreach ($featurelocs as $featureloc) { 01331 01332 // build the src name so we can keep track of the different parts for each feature 01333 $src = $featureloc->srcfeature_id->feature_id ."-". $featureloc->srcfeature_id->type_id->cvterm_id; 01334 01335 // orient the parts to the beginning of the feature sequence 01336 if (!empty($rel_locs[$src]['parts'])) { 01337 $parts = $rel_locs[$src]['parts']; 01338 $rparts = array(); // we will fill this up if we're on the reverse strand 01339 01340 foreach ($parts as $start => $types) { 01341 foreach ($types as $type_name => $type) { 01342 if ($featureloc->strand >= 0) { 01343 // this is on the forward strand. We need to convert the start on the src feature to the 01344 // start on this feature's sequence 01345 $parts[$start][$type_name]['start'] = $parts[$start][$type_name]['start'] - $featureloc->fmin; 01346 $parts[$start][$type_name]['end'] = $parts[$start][$type_name]['end'] - $featureloc->fmin; 01347 $parts[$start][$type_name]['type'] = $type_name; 01348 } 01349 else { 01350 // this is on the reverse strand. We need to swap the start and stop and calculate from the 01351 // begining of the reverse sequence 01352 $size = ($featureloc->fmax - $featureloc->fmin); 01353 $start_orig = $parts[$start][$type_name]['start']; 01354 $end_orig = $parts[$start][$type_name]['end']; 01355 $new_start = $size - ($end_orig - $featureloc->fmin); 01356 $new_end = $size - ($start_orig - $featureloc->fmin); 01357 01358 $rparts[$new_start][$type_name]['start'] = $new_start; 01359 $rparts[$new_start][$type_name]['end'] = $new_end; 01360 $rparts[$new_start][$type_name]['type'] = $type_name; 01361 } 01362 } 01363 } 01364 01365 // now sort the parts 01366 // if we're on the reverse strand we need to resort 01367 if ($featureloc->strand >= 0) { 01368 usort($parts, 'tripal_feature_sort_rel_parts_by_start'); 01369 } 01370 else { 01371 usort($rparts, 'tripal_feature_sort_rel_parts_by_start'); 01372 $parts = $rparts; 01373 } 01374 01375 $floc_sequences[$src]['src'] = $src; 01376 $floc_sequences[$src]['type'] = $featureloc->feature_id->type_id->name; 01377 $sequence = db_fetch_object(chado_query($sql, $featureloc->fmin + 1, ($featureloc->fmax - $featureloc->fmin), $featureloc->srcfeature_id->feature_id)); 01378 $residues = $sequence->residues; 01379 if ($featureloc->strand < 0) { 01380 $residues = tripal_feature_reverse_complement($residues); 01381 } 01382 $strand = '.'; 01383 if ($featureloc->strand == 1) { 01384 $strand = '+'; 01385 } 01386 elseif ($featureloc->strand == -1) { 01387 $strand = '-'; 01388 } 01389 $defline = $featureloc->feature_id->name . " " . $featureloc->srcfeature_id->name . ":" . ($featureloc->fmin + 1) . ".." . $featureloc->fmax . " " . $strand; 01390 $floc_sequences[$src]['formatted_seq'] = tripal_feature_color_sequence($residues, $parts, $defline); 01391 } 01392 } 01393 return $floc_sequences; 01394 } 01400 function tripal_feature_get_matched_alignments($feature) { 01401 // This function is for features that align through an intermediate such 01402 // as 'EST_match' or 'match'. This occurs in the case where two sequences 01403 // align but where one does not align perfectly. Some ESTs may be in a contig 01404 // but not all of the EST. Portions may overhang and not be included in the 01405 // consensus if quality is bad. 01406 // For example: 01407 // 01408 // Feature 1: Contig -------------------- 01409 // Feature 2: EST_match ------- 01410 // Feature 3: EST --------- 01411 // 01412 // The feature provided to the function will always be the feature 1. The 01413 // featureloc columns prefixed with 'right' (e.g. right_fmin) belong to the 01414 // alignment of feature 3 with feature 2 01415 // 01416 // Features may align to more than one feature and are not matches. We do 01417 // not want to include these, so we have to filter on the SO terms: 01418 // match, or %_match 01419 // 01420 $sql = "SELECT ". 01421 " FL1.featureloc_id as left_featureloc_id, ". 01422 " FL1.srcfeature_id as left_srcfeature_id, ". 01423 " FL1.feature_id as left_feature_id, ". 01424 " FL1.fmin as left_fmin, ". 01425 " FL1.is_fmin_partial as left_is_fmin_partial, ". 01426 " FL1.fmax as left_fmax, ". 01427 " FL1.is_fmax_partial as left_is_fmax_partial, ". 01428 " FL1.strand as left_strand, ". 01429 " FL1.phase as left_phase, ". 01430 " FL1.locgroup as left_locgroup, ". 01431 " FL1.rank as left_rank, ". 01432 " FL2.featureloc_id as right_featureloc_id, ". 01433 " FL2.srcfeature_id as right_srcfeature_id, ". 01434 " FL2.feature_id as right_feature_id, ". 01435 " FL2.fmin as right_fmin, ". 01436 " FL2.is_fmin_partial as right_is_fmin_partial, ". 01437 " FL2.fmax as right_fmax, ". 01438 " FL2.is_fmax_partial as right_is_fmax_partial, ". 01439 " FL2.strand as right_strand, ". 01440 " FL2.phase as right_phase, ". 01441 " FL2.locgroup as right_locgroup, ". 01442 " FL2.rank as right_rank ". 01443 "FROM feature F1 ". 01444 " INNER JOIN featureloc FL1 on FL1.srcfeature_id = F1.feature_id ". 01445 " INNER JOIN feature F2 on FL1.feature_id = F2.feature_id ". 01446 " INNER JOIN featureloc FL2 on FL2.feature_id = F2.feature_id ". 01447 " INNER JOIN feature F3 on FL2.srcfeature_id = F3.feature_id ". 01448 " INNER JOIN cvterm CVT2 on F2.type_id = CVT2.cvterm_id ". 01449 "WHERE F1.feature_id = %d and NOT F3.feature_id = %d ". 01450 " AND (CVT2.name = 'match' or CVT2.name like '%_match') ". 01451 "ORDER BY FL1.fmin"; 01452 01453 $results = chado_query($sql, $feature->feature_id, $feature->feature_id); 01454 01455 // iterate through the results and add them to our featurelocs array 01456 $featurelocs = array(); 01457 while ($fl = db_fetch_object($results)) { 01458 $featurelocs[] = $fl ; 01459 } 01460 return $featurelocs; 01461 } 01467 function tripal_feature_load_organism_feature_counts($organism) { 01468 01469 // don't show the browser if the settings in the admin page is turned off 01470 // instead return the array indicating the status of the browser 01471 $show_counts = variable_get('tripal_feature_summary_setting', 'show_feature_summary'); 01472 if (strcmp($show_counts, 'show_feature_summary')!=0) { 01473 return array('enabled' => FALSE ); 01474 } 01475 01476 01477 $args = array(); 01478 $names = array(); 01479 $order = array(); 01480 01481 // build the where clause for the SQL statement if we have a custom term list 01482 // we'll also keep track of the names the admin provided (if any) and the 01483 // order that the terms should appear. 01484 $is_custom = 0; 01485 $temp = rtrim(variable_get('tripal_feature_summary_report_mapping', '')); 01486 $where = ''; 01487 if ($temp) { 01488 $is_custom = 1; 01489 $temp = explode("\n", $temp); 01490 foreach ($temp as $key => $value) { 01491 // separate the key value pairs 01492 $temp2 = explode("=", $value); 01493 $feature_type = rtrim($temp2[0]); 01494 $args[] = $feature_type; 01495 $order[] = $feature_type; 01496 // if a new name is provided then use that otherwise just 01497 // use the feature type 01498 if (count($temp2) == 2) { 01499 $names[] = rtrim($temp2[1]); 01500 } 01501 else { 01502 $names[] = $feature_type; 01503 } 01504 $where .= "OFC.feature_type = '%s' OR \n"; 01505 } 01506 if ($where) { 01507 $where = drupal_substr($where, 0, -5); # remove OR from the end 01508 $where = "($where) AND"; 01509 } 01510 } 01511 01512 // get the feature counts. This is dependent on a materialized view 01513 // installed with the organism module 01514 $sql = " 01515 SELECT OFC.num_features,OFC.feature_type,CVT.definition 01516 FROM {organism_feature_count} OFC 01517 INNER JOIN {cvterm} CVT on OFC.cvterm_id = CVT.cvterm_id 01518 WHERE $where organism_id = %d 01519 ORDER BY num_features desc 01520 "; 01521 $args[] = $organism->organism_id; 01522 $org_features = chado_query($sql, $args); 01523 01524 // iterate through the types 01525 $types = array(); 01526 while ($type = db_fetch_object($org_features)) { 01527 $types[$type->feature_type] = $type; 01528 // if we don't have an order this means we didn't go through the loop 01529 // above to set the names, so do that now 01530 if (!$is_custom) { 01531 $names[] = $type->feature_type; 01532 $order[] = $type->feature_type; 01533 } 01534 } 01535 01536 # now reorder the types 01537 $ordered_types = array(); 01538 foreach ($order as $type) { 01539 $ordered_types[] = $types[$type]; 01540 } 01541 return array( 'types' => $ordered_types, 'names' => $names, 'enabled' => TRUE ); 01542 } 01548 function tripal_feature_load_organism_feature_browser($organism) { 01549 01550 if (!$organism) { 01551 return array(); 01552 } 01553 01554 // don't show the browser if the settings in the admin page is turned off 01555 // instead return the array indicating the status of the browser 01556 $show_browser = variable_get('tripal_feature_browse_setting', 'show_feature_browser'); 01557 if (strcmp($show_browser, 'show_feature_browser')!=0) { 01558 return array('enabled' => FALSE); 01559 } 01560 01561 // get the list of available sequence ontology terms for which 01562 // we will build drupal pages from features in chado. If a feature 01563 // is not one of the specified typse we won't build a node for it. 01564 $allowed_types = variable_get('chado_browser_feature_types', 'EST contig'); 01565 $allowed_types = preg_replace("/[\s\n\r]+/", " ", $allowed_types); 01566 $so_terms = split(' ', $allowed_types); 01567 01568 // perform the query 01569 $values = array( 01570 'organism_id' => $organism->organism_id, 01571 'type_id' => array( 01572 'name' => $so_terms 01573 ), 01574 ); 01575 $columns = array('feature_id', 'name', 'uniquename', 'type_id'); 01576 $options = array( 01577 'pager' => array('limit' => 10, 'element' => 0), 01578 'order_by' => array('name' => 'ASC'), 01579 ); 01580 $features = tripal_core_chado_select('feature', $columns, $values, $options); 01581 $pager = theme('pager'); 01582 01583 // add the node ids and types 01584 $nsql = "SELECT nid FROM {chado_feature} WHERE feature_id = %d"; 01585 $tsql = "SELECT name FROM {cvterm} WHERE cvterm_id = %d"; 01586 foreach ($features as $feature) { 01587 $node = db_fetch_object(db_query($nsql, $feature->feature_id)); 01588 $type = db_fetch_object(chado_query($tsql, $feature->type_id)); 01589 $feature->nid = $node->nid; 01590 $feature->type_name = $type->name; 01591 } 01592 01593 return array( 'features' => $features, 'pager' => $pager, 'enabled' => TRUE ); 01594 } 01595 01603 function tripal_feature_load_library_feature_browser($library) { 01604 01605 // don't show the browser if the settings in the admin page is turned off 01606 // instead return the array indicating the status of the browser 01607 $show_browser = variable_get('tripal_library_feature_browse_setting', 'show_feature_browser'); 01608 if (strcmp($show_browser, 'show_feature_browser')!=0) { 01609 return array('enabled' => FALSE); 01610 } 01611 01612 // get a list of feature types to include in the browser 01613 $allowed_types = variable_get('chado_browser_feature_types', 'EST contig'); 01614 $allowed_types = preg_replace("/[\s\n\r]+/", " ", $allowed_types); 01615 $so_terms = split(' ', $allowed_types); 01616 $where_cvt = ""; 01617 foreach ($so_terms as $term) { 01618 $where_cvt .= "CVT.name = '$term' OR "; 01619 } 01620 $where_cvt = drupal_substr($where_cvt, 0, drupal_strlen($where_cvt)-3); # strip trailing 'OR' 01621 01622 // get the features for this library 01623 $sql = "SELECT F.name,F.feature_id,F.uniquename,CVT.name as cvname ". 01624 "FROM {feature} F ". 01625 " INNER JOIN {cvterm} CVT on F.type_id = CVT.cvterm_id ". 01626 " INNER JOIN {library_feature} LF on F.feature_id = LF.feature_id ". 01627 " INNER JOIN {library} L on LF.library_id = L.library_id ". 01628 "WHERE LF.library_id = %d and ($where_cvt) ". 01629 "ORDER BY feature_id ASC"; 01630 01631 // the counting SQL 01632 $csql = "SELECT count(*) ". 01633 "FROM {feature} F". 01634 " INNER JOIN {cvterm} CVT on F.type_id = CVT.cvterm_id ". 01635 " INNER JOIN {library_feature} LF on F.feature_id = LF.feature_id ". 01636 " INNER JOIN {library} L on LF.library_id = L.library_id ". 01637 "WHERE LF.library_id = %d and ($where_cvt) ". 01638 "GROUP BY L.library_id "; 01639 01640 $previous_db = tripal_db_set_active('chado'); // use chado database 01641 $org_features = pager_query($sql, 10, 0, $csql, $library->library_id); 01642 tripal_db_set_active($previous_db); // now use drupal database 01643 $pager = theme('pager'); 01644 01645 // prepare the query that will lookup node ids 01646 $sql = "SELECT nid FROM {chado_feature} ". 01647 "WHERE feature_id = %d"; 01648 $i=0; 01649 $features = array(); 01650 while ($feature = db_fetch_object($org_features)) { 01651 $node = db_fetch_object(db_query($sql, $feature->feature_id)); 01652 $feature->nid = $node->nid; 01653 $features[$i++] = $feature; 01654 } 01655 01656 return array( 'features' => $features, 'pager' => $pager, 'enabled' => TRUE ); 01657 } 01665 function tripal_feature_load_analysis_feature_browser($analysis) { 01666 01667 // don't show the browser if the settings in the admin page is turned off 01668 // instead return the array indicating the status of the browser 01669 $show_browser = variable_get('tripal_analysis_feature_browse_setting', 'show_feature_browser'); 01670 if (strcmp($show_browser, 'show_feature_browser')!=0) { 01671 return array('enabled' => FALSE); 01672 } 01673 01674 // get a list of feature types to include in the browser 01675 $allowed_types = variable_get('chado_browser_feature_types', 'EST contig'); 01676 $allowed_types = preg_replace("/[\s\n\r]+/", " ", $allowed_types); 01677 $so_terms = split(' ', $allowed_types); 01678 $where_cvt = ""; 01679 foreach ($so_terms as $term) { 01680 $where_cvt .= "CVT.name = '$term' OR "; 01681 } 01682 $where_cvt = drupal_substr($where_cvt, 0, drupal_strlen($where_cvt)-3); # strip trailing 'OR' 01683 01684 // get the features for this library 01685 $sql = "SELECT F.name,F.feature_id,F.uniquename,CVT.name as cvname ". 01686 "FROM {feature} F ". 01687 " INNER JOIN {cvterm} CVT on F.type_id = CVT.cvterm_id ". 01688 " INNER JOIN {analysisfeature} AF on F.feature_id = AF.feature_id ". 01689 " INNER JOIN {analysis} A on AF.analysis_id = A.analysis_id ". 01690 "WHERE A.analysis_id = %d and ($where_cvt) ". 01691 "ORDER BY feature_id ASC"; 01692 01693 // the counting SQL 01694 $csql = "SELECT count(*) ". 01695 "FROM {feature} F". 01696 " INNER JOIN {cvterm} CVT on F.type_id = CVT.cvterm_id ". 01697 " INNER JOIN {analysisfeature} AF on F.feature_id = AF.feature_id ". 01698 " INNER JOIN {analysis} A on AF.analysis_id = A.analysis_id ". 01699 "WHERE A.analysis_id = %d and ($where_cvt) ". 01700 "GROUP BY A.analysis_id "; 01701 01702 $previous_db = tripal_db_set_active('chado'); // use chado database 01703 $org_features = pager_query($sql, 10, 0, $csql, $analysis->analysis_id); 01704 tripal_db_set_active($previous_db); // now use drupal database 01705 $pager = theme('pager'); 01706 01707 // prepare the query that will lookup node ids 01708 $sql = "SELECT nid FROM {chado_feature} ". 01709 "WHERE feature_id = %d"; 01710 $i=0; 01711 $features = array(); 01712 while ($feature = db_fetch_object($org_features)) { 01713 $node = db_fetch_object(db_query($sql, $feature->feature_id)); 01714 $feature->nid = $node->nid; 01715 $features[$i++] = $feature; 01716 } 01717 01718 return array( 'features' => $features, 'pager' => $pager, 'enabled' => TRUE ); 01719 } 01720 01726 function tripal_feature_sort_rel_objects($a, $b) { 01727 return strnatcmp($a->fmin, $b->fmin); 01728 } 01729 01735 function tripal_feature_sort_rel_parts_by_start($a, $b) { 01736 foreach ($a as $type_name => $details) { 01737 $astart = $a[$type_name]['start']; 01738 break; 01739 } 01740 foreach ($b as $type_name => $details) { 01741 $bstart = $b[$type_name]['start']; 01742 break; 01743 } 01744 return strnatcmp($astart, $bstart); 01745 } 01746 01752 function tripal_feature_sort_rel_parts_by_end($a, $b) { 01753 $val = strnatcmp($b['end'], $a['end']); 01754 if ($val == 0) { 01755 return strcmp($a['type'], $b['type']); 01756 } 01757 return $val; 01758 } 01759 01765 function tripal_feature_color_sequence($sequence, $parts, $defline) { 01766 01767 01768 $types = array(); 01769 // first get the list of types so we can create a color legend 01770 foreach ($parts as $index => $t) { 01771 foreach ($t as $type_name => $details) { 01772 $types[$type_name] = 1; 01773 } 01774 } 01775 01776 $newseq .= "<div id=\"tripal_feature-featureloc_sequence-legend\">Legend: "; 01777 foreach ($types as $type_name => $present) { 01778 $newseq .= "<span id=\"tripal_feature-legend-$type_name\" class=\"tripal_feature-legend-item tripal_feature-featureloc_sequence-$type_name\" script=\"\">$type_name</span>"; 01779 } 01780 $newseq .= "</div>Hold the cursor over a type above to highlight its positions in the sequence below. The colors in the sequence below merge when types overlap."; 01781 01782 01783 // set the background color of the rows based on the type 01784 $pos = 0; 01785 $newseq .= "<pre id=\"tripal_feature-featureloc_sequence\">"; 01786 $newseq .= ">$defline\n"; 01787 01788 // iterate through the parts. They should be in order. 01789 $ends = array(); 01790 foreach ($parts as $index => $types) { 01791 01792 // get the start for this part. All types in this part start at the 01793 // same position so we only need the first record 01794 foreach ($types as $type => $child) { 01795 $start = $child['start']; 01796 break; 01797 } 01798 01799 // add in the sequence up to the start of this part 01800 for ($i = $pos; $i < $start; $i++) { 01801 $newseq .= $sequence{$pos}; 01802 $seqcount++; 01803 if ($seqcount % 50 == 0) { 01804 $newseq .= "\n"; 01805 } 01806 if (array_key_exists($pos, $ends)) { 01807 foreach ($ends[$pos] as $end) { 01808 $newseq .= "</span>"; 01809 } 01810 } 01811 $pos++; 01812 } 01813 01814 // we want to sort the parts by their end. We want the span tag to 01815 // to be added in the order the parts end. 01816 usort($types, 'tripal_feature_sort_rel_parts_by_end'); 01817 01818 // now add the child span for all types that start at this position 01819 foreach ($types as $type) { 01820 $class = "tripal_feature-featureloc_sequence-" . $type['type']; 01821 $newseq .= "<span class=\"$class\">"; 01822 // add the end position 01823 $end = $type['end']; 01824 $ends[$end][] = $end; 01825 } 01826 } 01827 01828 // add in rest of the sequence 01829 for ($i = $pos; $i <= strlen($sequence); $i++) { 01830 $newseq .= $sequence{$pos}; 01831 $seqcount++; 01832 if ($seqcount % 50 == 0) { 01833 $newseq .= "\n"; 01834 } 01835 if (array_key_exists($pos, $ends)) { 01836 foreach ($ends[$pos] as $end) { 01837 $newseq .= "</span>"; 01838 } 01839 } 01840 $pos++; 01841 } 01842 01843 $newseq .= "</pre>"; 01844 return $newseq; 01845 } 01846 01853 function chado_feature_view($node, $teaser = FALSE, $page = FALSE) { 01854 01855 if (!$teaser) { 01856 // use drupal's default node view: 01857 $node = node_prepare($node, $teaser); 01858 01859 // if we're building the node for searching then 01860 // we want to handle this within the module and 01861 // not allow theme customization. We don't want to 01862 // index all items (such as DNA sequence). 01863 if ($node->build_mode == NODE_BUILD_SEARCH_INDEX) { 01864 $node->content['index_version'] = array( 01865 '#value' => theme('tripal_feature_search_index', $node), 01866 '#weight' => 1, 01867 ); 01868 } 01869 elseif ($node->build_mode == NODE_BUILD_SEARCH_RESULT) { 01870 $node->content['index_version'] = array( 01871 '#value' => theme('tripal_feature_search_results', $node), 01872 '#weight' => 1, 01873 ); 01874 } 01875 else { 01876 // do nothing here, let the theme derived template handle display 01877 } 01878 } 01879 01880 return $node; 01881 } 01882 01889 function tripal_feature_nodeapi(&$node, $op, $teaser, $page) { 01890 01891 switch ($op) { 01892 // Note that this function only adds feature view to an organism node. 01893 // The view of a feature node is controled by the theme *.tpl file 01894 case 'view': 01895 switch ($node->type) { 01896 case 'chado_organism': 01897 // Show feature browser 01898 $types_to_show = array('chado_organism', 'chado_library'); 01899 if (in_array($node->type, $types_to_show, TRUE)) { 01900 $node->content['tripal_organism_feature_counts'] = array( 01901 '#value' => theme('tripal_organism_feature_counts', $node), 01902 ); 01903 $node->content['tripal_organism_feature_browser'] = array( 01904 '#value' => theme('tripal_organism_feature_browser', $node), 01905 ); 01906 } 01907 break; 01908 } 01909 break; 01910 } 01911 } 01912 01913 01919 function tripal_feature_preprocess_tripal_feature_relationships(&$variables) { 01920 // we want to provide a new variable that contains the matched features. 01921 $feature = $variables['node']->feature; 01922 01923 if (!$feature->all_relationships) { 01924 $feature->all_relationships = tripal_feature_get_feature_relationships($feature); 01925 } 01926 } 01932 function tripal_feature_preprocess_tripal_feature_alignments(&$variables) { 01933 01934 // we want to provide a new variable that contains the matched features. 01935 $feature = $variables['node']->feature; 01936 $feature = tripal_core_expand_chado_vars($feature, 'table', 'featureloc'); 01937 01938 // get alignments as child 01939 $cfeaturelocs = $feature->featureloc->feature_id; 01940 if (!$cfeaturelocs) { 01941 $cfeaturelocs = array(); 01942 } 01943 elseif (!is_array($cfeaturelocs)) { 01944 $cfeaturelocs = array($cfeaturelocs); 01945 } 01946 // get alignment as parent 01947 $pfeaturelocs = $feature->featureloc->srcfeature_id; 01948 if (!$pfeaturelocs) { 01949 $pfeaturelocs = array(); 01950 } 01951 elseif (!is_array($pfeaturelocs)) { 01952 $pfeaturelocs = array($pfeaturelocs); 01953 } 01954 01955 // get matched alignments (those with an itermediate 'match' or 'EST_match', etc 01956 $mfeaturelocs = tripal_feature_get_matched_alignments($feature); 01957 $feature->matched_featurelocs = tripal_feature_get_matched_alignments($feature); 01958 01959 // combine all three alignments into a single array for printing together in 01960 // a single list 01961 $alignments = array(); 01962 foreach ($pfeaturelocs as $featureloc) { 01963 // if type is a 'match' then ignore it. We will handle those below 01964 if (preg_match('/(^match$|^.*?_match|match_part)$/', $featureloc->feature_id->type_id->name)) { 01965 continue; 01966 } 01967 $alignment = new stdClass(); 01968 $alignment->record = $featureloc; 01969 $alignment->name = $featureloc->feature_id->name; 01970 $alignment->nid = $featureloc->feature_id->nid; 01971 $alignment->type = $featureloc->feature_id->type_id->name; 01972 $alignment->fmin = $featureloc->fmin; 01973 $alignment->fmax = $featureloc->fmax; 01974 $alignment->phase = $featureloc->phase; 01975 $alignment->strand = $featureloc->strand; 01976 $alignments[] = $alignment; 01977 } 01978 foreach ($cfeaturelocs as $featureloc) { 01979 // if type is a 'match' then ignore it. We will handle those below 01980 if (preg_match('/(^match$|^.*?_match|match_part)$/', $featureloc->feature_id->type_id->name)) { 01981 continue; 01982 } 01983 $alignment = new stdClass(); 01984 $alignment->record = $featureloc; 01985 $alignment->name = $featureloc->srcfeature_id->name; 01986 $alignment->nid = $featureloc->srcfeature_id->nid; 01987 $alignment->type = $featureloc->srcfeature_id->type_id->name; 01988 $alignment->fmin = $featureloc->fmin; 01989 $alignment->is_fmin_partial = $featureloc->is_fmin_partial; 01990 $alignment->fmax = $featureloc->fmax; 01991 $alignment->is_fmax_partial = $featureloc->is_fmax_partial; 01992 $alignment->phase = $featureloc->phase; 01993 $alignment->strand = $featureloc->strand; 01994 $alignments[] = $alignment; 01995 } 01996 // in matching features, the left feature is always the feature 01997 // provided to this function. 01998 foreach ($mfeaturelocs as $featureloc) { 01999 // get more information about the right feature 02000 $select = array('feature_id' => $featureloc->right_srcfeature_id); 02001 $rfeature = tripal_core_generate_chado_var('feature', $select); 02002 // now add to the list 02003 $alignment = new stdClass(); 02004 $alignment->record = $featureloc; 02005 $alignment->right_feature = $rfeature; 02006 $alignment->name = $rfeature->name; 02007 $alignment->nid = $rfeature->nid; 02008 $alignment->type = $rfeature->type_id->name; 02009 $alignment->fmin = $featureloc->left_fmin; 02010 $alignment->is_fmin_partial = $featureloc->left_is_fmin_partial; 02011 $alignment->fmax = $featureloc->left_fmax; 02012 $alignment->is_fmax_partial = $featureloc->left_is_fmax_partial; 02013 $alignment->phase = $featureloc->left_phase; 02014 $alignment->strand = $featureloc->left_strand; 02015 $alignment->right_fmin = $featureloc->right_fmin; 02016 $alignment->right_is_fmin_partial = $featureloc->right_is_fmin_partial; 02017 $alignment->right_fmax = $featureloc->right_fmax; 02018 $alignment->right_is_fmax_partial = $featureloc->right_is_fmax_partial; 02019 $alignment->right_phase = $featureloc->right_phase; 02020 $alignment->right_strand = $featureloc->right_strand; 02021 $alignments[] = $alignment; 02022 } 02023 $feature->all_featurelocs = $alignments; 02024 } 02030 function tripal_feature_preprocess_tripal_organism_feature_counts(&$variables) { 02031 $organism = $variables['node']->organism; 02032 $organism->feature_counts = tripal_feature_load_organism_feature_counts($organism); 02033 } 02034 02040 function tripal_feature_preprocess_tripal_organism_feature_browser(&$variables) { 02041 $organism = $variables['node']->organism; 02042 $organism->feature_browser = tripal_feature_load_organism_feature_browser($organism); 02043 } 02044 02050 function tripal_feature_preprocess_tripal_library_feature_browser(&$variables) { 02051 $library = $variables['node']->library; 02052 $library->feature_browser = tripal_feature_load_library_feature_browser($library); 02053 } 02054 02060 function tripal_feature_preprocess_tripal_analysis_feature_browser(&$variables) { 02061 $analysis = $variables['node']->analysis; 02062 $analysis->feature_browser = tripal_feature_load_analysis_feature_browser($analysis); 02063 } 02064 02070 function tripal_feature_cv_chart($chart_id) { 02071 02072 // we only want the chart to show feature types setup by the admin 02073 $temp = rtrim(variable_get('tripal_feature_summary_report_mapping', '')); 02074 $where = ''; 02075 if ($temp) { 02076 $temp = explode("\n", $temp); 02077 foreach ($temp as $key => $value) { 02078 $temp2 = explode("=", $value); 02079 $feature_type = rtrim($temp2[0]); 02080 $where .= "CNT.feature_type = '$feature_type' OR \n"; 02081 } 02082 if ($where) { 02083 $where = drupal_substr($where, 0, -5); # remove OR from the end 02084 $where = "($where) AND"; 02085 } 02086 } 02087 02088 $organism_id = preg_replace("/^tripal_feature_cv_chart_(\d+)$/", "$1", $chart_id); 02089 02090 // The CV module will create the JSON array necessary for buillding a 02091 // pie chart using jgChart and Google Charts. We have to pass to it 02092 // a table that contains count information, tell it which column 02093 // contains the cvterm_id and provide a filter for getting the 02094 // results we want from the table. 02095 $options = array( 02096 count_mview => 'organism_feature_count', 02097 cvterm_id_column => 'cvterm_id', 02098 count_column => 'num_features', 02099 size => '550x200', 02100 filter => "$where CNT.organism_id = $organism_id", 02101 ); 02102 return $options; 02103 } 02104 02110 function tripal_feature_cv_tree($tree_id) { 02111 02112 // The CV module will create the JSON array necessary for buillding a 02113 // pie chart using jgChart and Google Charts. We have to pass to it 02114 // a table that contains count information, tell it which column 02115 // contains the cvterm_id and provide a filter for getting the 02116 // results we want from the table. 02117 $organism_id = preg_replace("/^tripal_feature_cv_tree_(\d+)$/", "$1", $tree_id); 02118 $options = array( 02119 cv_id => tripal_cv_get_cv_id('sequence'), 02120 count_mview => 'organism_feature_count', 02121 cvterm_id_column => 'cvterm_id', 02122 count_column => 'num_features', 02123 filter => "CNT.organism_id = $organism_id", 02124 label => 'Features', 02125 ); 02126 return $options; 02127 } 02128 02129 02130 02136 function tripal_feature_del_vocabulary() { 02137 //include the file containing the required functions for adding taxonomy vocabs 02138 module_load_include('inc', 'taxonomy', 'taxonomy.admin'); 02139 02140 // get the vocabularies 02141 $vocabularies = taxonomy_get_vocabularies(); 02142 02143 // These taxonomic terms are hard coded because we 02144 // know we have these relationships in the chado tables 02145 // through foreign key relationships. The tripal 02146 // modules that correspond to these chado "modules" don't 02147 // need to be installed for the taxonomy to work. 02148 foreach ($vocabularies as $vocab) { 02149 if ($vocab->name == 'Feature Type') { 02150 taxonomy_del_vocabulary($vocab->vid); 02151 } 02152 if ($vocab->name == 'Organism') { 02153 taxonomy_del_vocabulary($vocab->vid); 02154 } 02155 if ($vocab->name == 'Library') { 02156 taxonomy_del_vocabulary($vocab->vid); 02157 } 02158 if ($vocab->name == 'Analysis') { 02159 taxonomy_del_vocabulary($vocab->vid); 02160 } 02161 } 02162 02163 } 02164 02165 02166 02172 function tripal_feature_return_fasta($feature, $desc) { 02173 $fasta = ">" . variable_get('chado_feature_accession_prefix', 'ID') . "$feature->feature_id|$feature->name"; 02174 $fasta .= " $desc\n"; 02175 $fasta .= wordwrap($feature->residues, 50, "\n", TRUE); 02176 $fasta .= "\n\n"; 02177 return $fasta; 02178 } 02184 function tripal_feature_job_describe_args($callback, $args) { 02185 02186 $new_args = array(); 02187 if ($callback == 'tripal_feature_load_fasta') { 02188 $new_args['FASTA file'] = $args[0]; 02189 $organism = tripal_core_chado_select('organism', array('genus', 'species'), array('organism_id' => $args[1])); 02190 $new_args['Organism'] = $organism[0]->genus . " " . $organism[0]->species; 02191 $new_args['Sequence Type'] = $args[2]; 02192 $new_args['Name Match Type'] = $args[14]; 02193 $new_args['Name RE'] = $args[4]; 02194 $new_args['Unique Name RE'] = $args[5]; 02195 02196 // add in the relationship arguments 02197 $new_args['Relationship Type'] = $args[8]; 02198 $new_args['Relationship Parent RE'] = $args[9]; 02199 $new_args['Relationship Parent Type'] = $args[10]; 02200 02201 // add in the database reference arguments 02202 if ($args[7]) { 02203 $db = tripal_core_chado_select('db', array('name'), array('db_id' => $args[7])); 02204 } 02205 $new_args['Database Reference'] = $db[0]->name; 02206 $new_args['Accession RE'] = $args[6]; 02207 $new_args['Method'] = $args[11]; 02208 02209 // add in the analysis 02210 if ($args[13]) { 02211 $analysis = tripal_core_chado_select('analysis', array('name'), array('analysis_id' => $args[13])); 02212 } 02213 $new_args['Analysis'] = $analysis[0]->name; 02214 } 02215 if ($callback == 'tripal_feature_delete_features') { 02216 if ($args[0]) { 02217 $organism = tripal_core_chado_select('organism', array('genus', 'species'), array('organism_id' => $args[0])); 02218 $new_args['Organism'] = $organism[0]->genus . " " . $organism[0]->species; 02219 } 02220 else { 02221 $new_args['Organism'] = ''; 02222 } 02223 02224 if ($args[1]) { 02225 $analysis = tripal_core_chado_select('analysis', array('name'), array('analysis_id' => $args[1])); 02226 $new_args['Analysis'] = $analysis[0]->name; 02227 } 02228 else { 02229 $new_args['Analysis'] = ''; 02230 } 02231 02232 $new_args['Sequence Type'] = $args[2]; 02233 $new_args['Is Unique Name'] = $args[3]; 02234 $new_args['Features Names'] = $args[4]; 02235 02236 } 02237 elseif ($callback == 'tripal_feature_load_gff3') { 02238 02239 $new_args['GFF File'] = $args[0]; 02240 $organism = tripal_core_chado_select('organism', array('genus', 'species'), array('organism_id' => $args[1])); 02241 $new_args['Organism'] = $organism[0]->genus . " " . $organism[0]->species; 02242 $analysis = tripal_core_chado_select('analysis', array('name'), array('analysis_id' => $args[2])); 02243 $new_args['Analysis'] = $analysis[0]->name; 02244 $new_args['Use a Transaction'] = ($args[7] == 1) ? "Yes" : "No"; 02245 $new_args['Import only new features'] = ($args[3] == 1) ? "Yes" : "No"; 02246 $new_args['Import all and update'] = ($args[4] == 1) ? "Yes" : "No"; 02247 $new_args['Import all and replace'] = ($args[5] == 1) ? "Yes" : "No"; 02248 $new_args['Delete features'] = ($args[6] == 1) ? "Yes" : "No"; 02249 $target_organism = tripal_core_chado_select('organism', array('genus', 'species'), array('organism_id' => $args[8])); 02250 $new_args['Target organism'] = $target_organism[0]->genus . " " . $target_organism[0]->species; 02251 $new_args['Target type'] = $args[9]; 02252 $new_args['Create target'] = ($args[10] == 1) ? "Yes" : "No"; 02253 $new_args['Starting line'] = $args[11]; 02254 $new_args['Landmark Type'] = $args[12]; 02255 $new_args['Alternate ID attribute'] = $args[13]; 02256 } 02257 if ($callback == 'tripal_feature_sync_features') { 02258 if ($args[0]) { 02259 $organism = tripal_core_chado_select('organism', array('genus', 'species'), array('organism_id' => $args[0])); 02260 $new_args['Organism'] = $organism[0]->genus . " " . $organism[0]->species; 02261 } 02262 else { 02263 $new_args['Organism'] = ''; 02264 } 02265 $new_args['Feature Types'] = $args[1]; 02266 } 02267 return $new_args; 02268 } 02269 02274 function tripal_feature_coder_ignore() { 02275 return array( 02276 'path' => drupal_get_path('module', 'tripal_feature'), 02277 'line prefix' => drupal_get_path('module', 'tripal_feature'), 02278 ); 02279 } 02280 02281 /* 02282 * Uses the value provided in the $id argument to find all features that match 02283 * that ID by name, featurename or synonym. If it matches uniquenly to a single 02284 * feature it will redirect to that feature page, otherwise, a list of matching 02285 * features is shown. 02286 */ 02287 function tripal_feature_match_features_page($id) { 02288 02289 $sql = " 02290 SELECT 02291 F.name, F.uniquename, F.feature_id, 02292 O.genus, O.species, O.organism_id, 02293 CVT.cvterm_id, CVT.name as type_name, 02294 CF.nid, 02295 array_agg(S.name) as synonyms 02296 FROM feature F 02297 INNER JOIN organism O on F.organism_id = O.organism_id 02298 INNER JOIN cvterm CVT on CVT.cvterm_id = F.type_id 02299 LEFT JOIN feature_synonym FS on FS.feature_id = F.feature_id 02300 LEFT JOIN synonym S on S.synonym_id = FS.synonym_id 02301 INNER JOIN public.chado_feature CF on CF.feature_id = F.feature_id 02302 WHERE 02303 F.uniquename = '%s' or 02304 F.name = '%s' or 02305 S.name = '%s' 02306 GROUP BY F.name, F.uniquename, F.feature_id, O.genus, O.species, 02307 O.organism_id, CVT.cvterm_id, CVT.name, CF.nid 02308 "; 02309 $results = chado_query($sql, $id, $id, $id); 02310 02311 $num_matches = 0; 02312 02313 // iterate through the matches and build the table for showing matches 02314 $header = array('Uniquename', 'Name', 'Type', 'Species', 'Synonyms'); 02315 $rows = array(); 02316 $curr_match; 02317 while ($match = db_fetch_object($results)) { 02318 $curr_match = $match; 02319 $synonyms = $match->synonyms; 02320 $synonyms = preg_replace('/[\"\{\}]/', '', $synonyms); 02321 $rows[] = array( 02322 $match->uniquename, 02323 "<a href=\"" . url("node/". $match->nid) ."\">" . $match->name . "</a>", 02324 $match->type_name, 02325 '<i>' . $match->genus . ' ' . $match->species . '</i>', 02326 $synonyms, 02327 ); 02328 $num_matches++; 02329 } 02330 02331 // if we have more than one match then generate the table, otherwise, redirect 02332 // to the matched feature 02333 if ($num_matches == 1) { 02334 drupal_goto(url("node/". $curr_match->nid)); 02335 } 02336 if ($num_matches == 0) { 02337 return "<p>No features matched the given name '$id'</p>"; 02338 } 02339 02340 $table_attrs = array( 02341 'class' => 'tripal-table tripal-table-horz' 02342 ); 02343 $output = "<p>The following features match the name '$id'.</p>"; 02344 $output .= theme_table($header, $rows, $table_attrs, $caption); 02345 return $output; 02346 }