|
Tripal 0.3b
|
00001 <?php 00002 00003 /** 00004 * @defgroup tripal_feature Feature 00005 * @{ 00006 * Provides functions for managing chado features including creating details pages for each feature 00007 * @} 00008 * @ingroup tripal_modules 00009 */ 00010 00011 require_once "tripal_feature.admin.inc"; 00012 require_once "syncFeatures.php"; 00013 require_once "indexFeatures.php"; 00014 require_once "fasta_loader.php"; 00015 require_once "gff_loader.php"; 00016 00017 require_once "tripal_feature.api.inc"; 00018 00019 require_once "tripal_feature-secondary_tables.inc"; 00020 require_once "tripal_feature-properties.inc"; 00021 require_once "tripal_feature-relationships.inc"; 00022 require_once "tripal_feature-db_references.inc"; 00023 00024 00025 /** 00026 * 00027 * @ingroup tripal_feature 00028 */ 00029 function tripal_feature_init(){ 00030 00031 // add the jGCharts JS and CSS 00032 drupal_add_js (drupal_get_path('theme', 'tripal').'/js/tripal_feature.js'); 00033 drupal_add_js (drupal_get_path('theme', 'tripal').'/js/jgcharts/jgcharts.js'); 00034 00035 drupal_add_css(drupal_get_path('theme', 'tripal'). 00036 '/css/tripal_feature.css'); 00037 } 00038 00039 /** 00040 * Implements hook_views_api() 00041 * 00042 * Purpose: Essentially this hook tells drupal that there is views support for 00043 * for this module which then includes tripal_db.views.inc where all the 00044 * views integration code is 00045 * 00046 * @ingroup tripal_feature 00047 */ 00048 function tripal_feature_views_api() { 00049 return array( 00050 'api' => 2.0, 00051 ); 00052 } 00053 00054 /** 00055 * Display help and module information 00056 * 00057 * @param 00058 * path which path of the site we're displaying help 00059 * @param 00060 * arg array that holds the current path as would be returned from arg() function 00061 * 00062 * @return 00063 * help text for the path 00064 * 00065 * @ingroup tripal_feature 00066 */ 00067 function tripal_feature_help($path, $arg) { 00068 $output = ''; 00069 switch ($path) { 00070 case "admin/help#tripal_feature": 00071 $output='<p>'.t("Displays links to nodes created on this date").'</p>'; 00072 break; 00073 } 00074 return $output; 00075 } 00076 00077 /** 00078 * Provide information to drupal about the node types that we're creating 00079 * in this module 00080 * 00081 * @ingroup tripal_feature 00082 */ 00083 function tripal_feature_node_info() { 00084 $nodes = array(); 00085 00086 $nodes['chado_feature'] = array( 00087 'name' => t('Feature'), 00088 'module' => 'chado_feature', 00089 'description' => t('A feature from the chado database'), 00090 'has_title' => FALSE, 00091 'title_label' => t('Feature'), 00092 'has_body' => FALSE, 00093 'body_label' => t('Feature Description'), 00094 'locked' => TRUE 00095 ); 00096 return $nodes; 00097 } 00098 00099 /** 00100 * Set the permission types that the chado module uses. Essentially we 00101 * want permissionis that protect creation, editing and deleting of chado 00102 * data objects 00103 * 00104 * @ingroup tripal_feature 00105 */ 00106 function tripal_feature_perm(){ 00107 return array( 00108 'access chado_feature content', 00109 'create chado_feature content', 00110 'delete chado_feature content', 00111 'edit chado_feature content', 00112 'manage chado_feature aggregator', 00113 ); 00114 } 00115 00116 /** 00117 * Set the permission types that the module uses. 00118 * 00119 * @ingroup tripal_feature 00120 */ 00121 function chado_feature_access($op, $node, $account) { 00122 if ($op == 'create') { 00123 return user_access('create chado_feature content', $account); 00124 } 00125 00126 if ($op == 'update') { 00127 if (user_access('edit chado_feature content', $account)) { 00128 return TRUE; 00129 } 00130 } 00131 if ($op == 'delete') { 00132 if (user_access('delete chado_feature content', $account)) { 00133 return TRUE; 00134 } 00135 } 00136 if ($op == 'view') { 00137 if (user_access('access chado_feature content', $account)) { 00138 return TRUE; 00139 } 00140 } 00141 return FALSE; 00142 } 00143 /** 00144 * Menu items are automatically added for the new node types created 00145 * by this module to the 'Create Content' Navigation menu item. This function 00146 * adds more menu items needed for this module. 00147 * 00148 * @ingroup tripal_feature 00149 */ 00150 function tripal_feature_menu() { 00151 $items = array(); 00152 00153 // the administative settings menu 00154 $items['admin/tripal/tripal_feature'] = array( 00155 'title' => 'Features', 00156 'description' => 'Basic Description of Tripal Organism Module Functionality', 00157 'page callback' => 'tripal_feature_module_description_page', 00158 'access arguments' => array('administer site configuration'), 00159 'type' => MENU_NORMAL_ITEM, 00160 ); 00161 $items['admin/tripal/tripal_feature/configuration'] = array( 00162 'title' => 'Feature Configuration', 00163 'description' => 'Settings for Chado Features', 00164 'page callback' => 'drupal_get_form', 00165 'page arguments' => array('tripal_feature_admin'), 00166 'access arguments' => array('administer site configuration'), 00167 'type' => MENU_NORMAL_ITEM, 00168 ); 00169 $items['admin/tripal/tripal_feature/fasta_loader'] = array( 00170 'title' => 'Import a multi-FASTA file', 00171 'description' => 'Load sequences from a multi-FASTA file into Chado', 00172 'page callback' => 'drupal_get_form', 00173 'page arguments' => array('tripal_feature_fasta_load_form'), 00174 'access arguments' => array('administer site configuration'), 00175 'type' => MENU_NORMAL_ITEM, 00176 ); 00177 $items['admin/tripal/tripal_feature/gff3_load'] = array( 00178 'title' => 'Import a GFF3 file', 00179 'description' => 'Import a GFF3 file into Chado', 00180 'page callback' => 'drupal_get_form', 00181 'page arguments' => array('tripal_core_gff3_load_form'), 00182 'access arguments' => array('access administration pages'), 00183 'type' => MENU_NORMAL_ITEM, 00184 ); 00185 00186 // Adding Secondary Properties 00187 00188 00189 $items['node/%tf_node/tf_properties'] = array( 00190 'title' => t('Add Properties & Synonyms'), 00191 'description' => t('Settings for Features'), 00192 'page callback' => 'tripal_feature_add_ALL_property_page', 00193 'page arguments' => array(1), 00194 'access arguments' => array('create chado_feature content'), 00195 'type' => MENU_CALLBACK 00196 ); 00197 00198 $items['node/%tf_node/tf_db_references'] = array( 00199 'title' => t('Add Database References'), 00200 'description' => t('Settings for Features'), 00201 'page callback' => 'tripal_feature_add_ALL_dbreferences_page', 00202 'page arguments' => array(1), 00203 'access arguments' => array('create chado_feature content'), 00204 'type' => MENU_CALLBACK 00205 ); 00206 00207 $items['node/%tf_node/tf_relationships'] = array( 00208 'title' => t('Add Relationships'), 00209 'description' => t('Settings for Features'), 00210 'page callback' => 'tripal_feature_add_ALL_relationships_page', 00211 'page arguments' => array(1), 00212 'access arguments' => array('create chado_feature content'), 00213 'type' => MENU_CALLBACK 00214 ); 00215 //Edit/Deleting Secondary Properties------------- 00216 /** 00217 $items['node/%tf_node/tf_edit_properties'] = array( 00218 'title' => t('Edit Properties'), 00219 'description' => t('Settings for Features'), 00220 'page callback' => 'tripal_feature_edit_ALL_properties_page', 00221 'page arguments' => array(1), 00222 'access arguments' => array('edit chado_feature content'), 00223 'type' => MENU_LOCAL_TASK, 00224 'weight' => 8, 00225 ); 00226 00227 $items['node/%tf_node/tf_edit_relationships'] = array( 00228 'title' => t('Edit Relationships'), 00229 'description' => t('Settings for Feature'), 00230 'page callback' => 'tripal_feature_edit_ALL_relationships_page', 00231 'page arguments' => array(1), 00232 'access arguments' => array('edit chado_feature content'), 00233 'type' => MENU_LOCAL_TASK, 00234 'weight' => 9, 00235 ); 00236 */ 00237 $items['node/%tf_node/tf_edit_db_references'] = array( 00238 'title' => t('Edit References'), 00239 'description' => t('Settings for Feature'), 00240 'page callback' => 'tripal_feature_edit_ALL_dbreferences_page', 00241 'page arguments' => array(1), 00242 'access arguments' => array('edit chado_feature content'), 00243 'type' => MENU_LOCAL_TASK, 00244 'weight' => 10, 00245 ); 00246 00247 // managing relationship aggregates 00248 $items['admin/tripal/tripal_feature/aggregate'] = array( 00249 'title' => 'Feature Relationship Aggegators', 00250 'description' => t('Features have relationships with other features and it may be desirable to aggregate the content from one ore more child or parent feature.'), 00251 'page callback' => 'tripal_feature_aggregator_page', 00252 'access arguments' => array('manage chado_feature aggregator'), 00253 'type' => MENU_NORMAL_ITEM, 00254 ); 00255 00256 $items['admin/tripal/tripal_feature/aggregate/new'] = array( 00257 'title' => 'Add an Aggregator', 00258 'page callback' => 'drupal_get_form', 00259 'page arguments' => array('tripal_feature_aggregator_form'), 00260 'access arguments' => array('manage chado_feature aggregator'), 00261 'type' => MENU_NORMAL_ITEM, 00262 ); 00263 $items['admin/tripal/tripal_feature/aggregate/edit/js'] = array( 00264 'title' => 'Edit an Aggegator', 00265 'page callback' => 'tripal_feature_aggregator_ajax_edit', 00266 'access arguments' => array('manage chado_feature aggregator'), 00267 'type' => MENU_CALLBACK, 00268 ); 00269 00270 return $items; 00271 } 00272 00273 /** 00274 * Implements Menu wildcard_load hook 00275 * Purpose: Allows the node ID of a chado feature to be dynamically 00276 * pulled from the path. The node is loaded from this node ID 00277 * and supplied to the page as an arguement 00278 * 00279 * @ingroup tripal_feature 00280 */ 00281 function tf_node_load($nid) { 00282 if (is_numeric($nid)) { 00283 $node = node_load($nid); 00284 if ($node->type == 'chado_feature') { 00285 return $node; 00286 } 00287 } 00288 return FALSE; 00289 } 00290 /** 00291 * 00292 * 00293 * @ingroup tripal_feature 00294 */ 00295 function tripal_feature_block($op = 'list', $delta = 0, $edit=array()){ 00296 switch($op) { 00297 case 'list': 00298 $blocks['references']['info'] = t('Tripal Feature References'); 00299 $blocks['references']['cache'] = BLOCK_NO_CACHE; 00300 00301 $blocks['base']['info'] = t('Tripal Feature Details'); 00302 $blocks['base']['cache'] = BLOCK_NO_CACHE; 00303 00304 $blocks['sequence']['info'] = t('Tripal Feature Sequence'); 00305 $blocks['sequence']['cache'] = BLOCK_NO_CACHE; 00306 00307 $blocks['synonyms']['info'] = t('Tripal Feature Synonyms'); 00308 $blocks['synonyms']['cache'] = BLOCK_NO_CACHE; 00309 00310 $blocks['properties']['info'] = t('Tripal Feature Properties'); 00311 $blocks['properties']['cache'] = BLOCK_NO_CACHE;; 00312 00313 $blocks['featureloc_sequences']['info'] = t('Tripal Formatted Sequence'); 00314 $blocks['featureloc_sequences']['cache'] = BLOCK_NO_CACHE; 00315 00316 $blocks['alignments']['info'] = t('Tripal Feature Alignments'); 00317 $blocks['alignments']['cache'] = BLOCK_NO_CACHE; 00318 00319 $blocks['relationships']['info'] = t('Tripal Feature Relationships'); 00320 $blocks['relationships']['cache'] = BLOCK_NO_CACHE; 00321 00322 $blocks['org_feature_counts']['info'] = t('Tripal Organism Feature Counts'); 00323 $blocks['org_feature_counts']['cache'] = BLOCK_NO_CACHE; 00324 00325 $blocks['org_feature_browser']['info'] = t('Tripal Organism Feature Browser'); 00326 $blocks['org_feature_browser']['cache'] = BLOCK_NO_CACHE; 00327 return $blocks; 00328 00329 00330 case 'view': 00331 if(user_access('access chado_feature content') and arg(0) == 'node' and is_numeric(arg(1))) { 00332 $nid = arg(1); 00333 $node = node_load($nid); 00334 00335 $block = array(); 00336 switch($delta){ 00337 case 'references': 00338 $block['subject'] = t('References'); 00339 $block['content'] = theme('tripal_feature_references',$node); 00340 break; 00341 case 'base': 00342 $block['subject'] = t('Feature Details'); 00343 $block['content'] = theme('tripal_feature_base',$node); 00344 break; 00345 case 'synonyms': 00346 $block['subject'] = t('Synonyms'); 00347 $block['content'] = theme('tripal_feature_synonyms',$node); 00348 break; 00349 case 'properties': 00350 $block['subject'] = t('Properties'); 00351 $block['content'] = theme('tripal_feature_properties',$node); 00352 break;; 00353 case 'sequence': 00354 $block['subject'] = t('Sequence'); 00355 $block['content'] = theme('tripal_feature_sequence',$node); 00356 break; 00357 case 'featureloc_sequences': 00358 $block['subject'] = t('Formatted Sequences'); 00359 $block['content'] = theme('tripal_feature_featureloc_sequences',$node); 00360 break; 00361 case 'alignments': 00362 $block['subject'] = t('Alignments'); 00363 $block['content'] = theme('tripal_feature_featurelocs',$node); 00364 break; 00365 case 'relationships': 00366 $block['subject'] = t('Relationships'); 00367 $block['content'] = theme('tripal_feature_relationships',$node); 00368 break; 00369 case 'org_feature_counts': 00370 $block['subject'] = t('Feature Type Summary'); 00371 $block['content'] = theme('tripal_organism_feature_counts', $node); 00372 break; 00373 case 'org_feature_browser': 00374 $block['subject'] = t('Feature Browser'); 00375 $block['content'] = theme('tripal_organism_feature_browser', $node); 00376 break; 00377 default : 00378 } 00379 return $block; 00380 } 00381 00382 } 00383 } 00384 /** 00385 * When a new chado_feature node is created we also need to add information 00386 * to our chado_feature table. This function is called on insert of a new node 00387 * of type 'chado_feature' and inserts the necessary information. 00388 * 00389 * @ingroup tripal_feature 00390 */ 00391 function chado_feature_insert($node){ 00392 // remove spaces, newlines from residues 00393 $residues = preg_replace("/[\n\r\s]/","",$node->residues); 00394 $obsolete = 'FALSE'; 00395 if($node->is_obsolete){ 00396 $obsolete = 'TRUE'; 00397 } 00398 $values = array( 00399 'cv_id' => array( 00400 'name' => 'sequence' 00401 ), 00402 'name' => $node->feature_type 00403 ); 00404 $type = tripal_core_chado_select('cvterm',array('cvterm_id'),$values); 00405 $values = array( 00406 'organism_id' => $node->organism_id, 00407 'name' => $node->fname, 00408 'uniquename' => $node->uniquename, 00409 'residues' => $residues, 00410 'seqlen' => strlen($residues), 00411 'is_obsolete' => $obsolete, 00412 'type_id' => $type[0]->cvterm_id, 00413 'md5checksum' => md5($residues) 00414 ); 00415 00416 $istatus = tripal_core_chado_insert('feature', $values); 00417 if (!$istatus) { 00418 drupal_set_message('Unable to add feature.', 'warning'); 00419 watchdog('tripal_organism', 00420 'Insert feature: Unable to create feature where values: %values', 00421 array('%values' => print_r($values, TRUE)), 00422 WATCHDOG_WARNING 00423 ); 00424 } 00425 $values = array( 00426 'organism_id' => $node->organism_id, 00427 'uniquename' => $node->uniquename, 00428 'type_id' => $type[0]->cvterm_id, 00429 ); 00430 $feature = tripal_core_chado_select('feature',array('feature_id'),$values); 00431 // add the genbank accession and synonyms 00432 chado_feature_add_synonyms($node->synonyms,$feature[0]->feature_id); 00433 00434 // make sure the entry for this feature doesn't already exist in the chado_feature table 00435 // if it doesn't exist then we want to add it. 00436 $node_check_sql = "SELECT * FROM {chado_feature} ". 00437 "WHERE feature_id = '%s'"; 00438 $node_check = db_fetch_object(db_query($node_check_sql,$feature[0]->feature_id)); 00439 if(!$node_check){ 00440 // next add the item to the drupal table 00441 $sql = "INSERT INTO {chado_feature} (nid, vid, feature_id, sync_date) ". 00442 "VALUES (%d, %d, %d, " . time() . ")"; 00443 db_query($sql,$node->nid,$node->vid,$feature[0]->feature_id); 00444 } 00445 } 00446 /** 00447 * 00448 * 00449 * @ingroup tripal_feature 00450 */ 00451 function chado_feature_update($node){ 00452 if($node->revision){ 00453 // TODO -- decide what to do about revisions 00454 } else { 00455 $residues = preg_replace("/[\n\r\s]/","",$node->residues); 00456 $obsolete = 'FALSE'; 00457 if($node->is_obsolete){ 00458 $obsolete = 'TRUE'; 00459 } 00460 00461 // get the feature type id 00462 $values = array( 00463 'cv_id' => array( 00464 'name' => 'sequence' 00465 ), 00466 'name' => $node->feature_type 00467 ); 00468 $type = tripal_core_chado_select('cvterm',array('cvterm_id'),$values); 00469 00470 $feature_id = chado_get_id_for_node('feature',$node) ; 00471 00472 if(sizeof($type) > 0){ 00473 $match = array( 00474 'feature_id' => $feature_id, 00475 ); 00476 $values = array( 00477 'organism_id' => $node->organism_id, 00478 'name' => $node->fname, 00479 'uniquename' => $node->uniquename, 00480 'residues' => $residues, 00481 'seqlen' => strlen($residues), 00482 'is_obsolete' => $obsolete, 00483 'type_id' => $type[0]->cvterm_id, 00484 'md5checksum' => md5($residues) 00485 ); 00486 $status = tripal_core_chado_update('feature', $match,$values); 00487 00488 // add the genbank synonyms 00489 chado_feature_add_synonyms($node->synonyms,$feature_id); 00490 } 00491 else { 00492 drupal_set_message('Unable to update feature.', 'warning'); 00493 watchdog('tripal_organism', 00494 'Update feature: Unable to update feature where values: %values', 00495 array('%values' => print_r($values, TRUE)), 00496 WATCHDOG_WARNING 00497 ); 00498 } 00499 } 00500 } 00501 /** 00502 * 00503 * 00504 * @ingroup tripal_feature 00505 */ 00506 function chado_feature_delete($node){ 00507 00508 $feature_id = chado_get_id_for_node('feature',$node); 00509 00510 // remove the drupal content 00511 $sql_del = "DELETE FROM {chado_feature} ". 00512 "WHERE nid = %d ". 00513 "AND vid = %d"; 00514 db_query($sql_del, $node->nid, $node->vid); 00515 $sql_del = "DELETE FROM {node} ". 00516 "WHERE nid = %d ". 00517 "AND vid = %d"; 00518 db_query($sql_del, $node->nid, $node->vid); 00519 $sql_del = "DELETE FROM {node_revisions} ". 00520 "WHERE nid = %d ". 00521 "AND vid = %d"; 00522 db_query($sql_del, $node->nid, $node->vid); 00523 00524 00525 // Remove data from feature tables of chado database. This will 00526 // cause a cascade delete and remove all data in referencing tables 00527 // for this feature 00528 $previous_db = tripal_db_set_active('chado'); 00529 db_query("DELETE FROM {feature} WHERE feature_id = %d", $feature_id); 00530 tripal_db_set_active($previous_db); 00531 00532 drupal_set_message("The feature and all associated data were removed from ". 00533 "chado"); 00534 00535 } 00536 /** 00537 * 00538 * 00539 * @ingroup tripal_feature 00540 */ 00541 function chado_feature_add_synonyms($synonyms,$feature_id){ 00542 00543 // make sure we only have a single space between each synonym 00544 $synonyms = preg_replace("/[\s\n\r]+/"," ",$synonyms); 00545 // split the synonyms into an array based on a space as the delimieter 00546 $syn_array = array(); 00547 $syn_array = explode(" ",$synonyms); 00548 00549 // use the chado database 00550 $previous_db = tripal_db_set_active('chado'); 00551 00552 // remove any old synonyms 00553 $feature_syn_dsql = "DELETE FROM {feature_synonym} WHERE feature_id = %d"; 00554 if(!db_query($feature_syn_dsql,$feature_id)){ 00555 $error .= "Could not remove synonyms from feature. "; 00556 } 00557 00558 // return if we don't have any synonmys to add 00559 if(!$synonyms){ 00560 tripal_db_set_active($previous_db); 00561 return; 00562 } 00563 // iterate through each synonym and add it to the database 00564 foreach($syn_array as $syn){ 00565 // skip this item if it's empty 00566 if(!$syn){ break; } 00567 00568 // check to see if we have this accession number already in the database 00569 // if so then don't add it again. it messes up drupal if the insert fails. 00570 // It is possible for the accession number to be present and not the feature 00571 $synonym_sql = "SELECT synonym_id FROM {synonym} ". 00572 "WHERE name = '%s'"; 00573 $synonym = db_fetch_object(db_query($synonym_sql,$syn)); 00574 if(!$synonym){ 00575 $synonym_isql = "INSERT INTO {synonym} (name,synonym_sgml,type_id) ". 00576 "VALUES ('%s','%s', ". 00577 " (SELECT cvterm_id ". 00578 " FROM {CVTerm} CVT ". 00579 " INNER JOIN CV ON CVT.cv_id = CV.cv_id ". 00580 " WHERE CV.name = 'feature_property' and CVT.name = 'synonym'))"; 00581 if(!db_query($synonym_isql,$syn,$syn)){ 00582 $error .= "Could not add synonym. "; 00583 } 00584 // now get the synonym we just added 00585 $synonym_sql = "SELECT synonym_id FROM {synonym} ". 00586 "WHERE name = '%s'"; 00587 $synonym = db_fetch_object(db_query($synonym_sql,$syn)); 00588 } 00589 00590 // now add in our new sysnonym 00591 $feature_syn_isql = "INSERT INTO {feature_synonym} (synonym_id,feature_id,pub_id) ". 00592 "VALUES (%d,%d,1)"; 00593 if(!db_query($feature_syn_isql,$synonym->synonym_id,$feature_id)){ 00594 $error .= "Could not add synonyms to feature. "; 00595 } 00596 } 00597 00598 // return to the drupal database 00599 tripal_db_set_active($previous_db); 00600 return $error; 00601 00602 } 00603 /** 00604 * 00605 * 00606 * @ingroup tripal_feature 00607 */ 00608 function chado_feature_add_gbaccession($accession,$feature_id){ 00609 00610 // use chado database 00611 $previous_db = tripal_db_set_active('chado'); 00612 00613 // remove any old accession from genbank dbEST 00614 $fdbxref_dsql = "DELETE FROM {feature_dbxref} ". 00615 "WHERE feature_id = %d and dbxref_id IN ". 00616 " (SELECT DBX.dbxref_id FROM {dbxref} DBX ". 00617 " INNER JOIN DB ON DB.db_id = DBX.db_id ". 00618 " INNER JOIN feature_dbxref FDBX ON DBX.dbxref_id = FDBX.dbxref_id ". 00619 " WHERE DB.name = 'DB:Genbank' and FDBX.feature_id = %d)"; 00620 if(!db_query($fdbxref_dsql,$feature_id,$feature_id)){ 00621 $error .= "Could not remove accession from feature. "; 00622 } 00623 00624 // if we don't have an accession number to add then just return 00625 if(!$accession){ 00626 tripal_db_set_active($previous_db); 00627 return; 00628 } 00629 // get the db_id 00630 $db_sql = "SELECT db_id FROM {DB} ". 00631 "WHERE name = 'DB:Genbank_est'"; 00632 $db = db_fetch_object(db_query($db_sql)); 00633 00634 // check to see if we have this accession number already in the database 00635 // if so then don't add it again. it messes up drupal if the insert fails. 00636 // It is possible for the accession number to be present and not the feature 00637 $dbxref_sql = "SELECT dbxref_id FROM {dbxref} ". 00638 "WHERE db_id = %d and accession = '%s'"; 00639 $dbxref = db_fetch_object(db_query($dbxref_sql,$db->db_id,$accession)); 00640 if(!$dbxref){ 00641 // add the accession number 00642 $dbxref_isql = "INSERT INTO {dbxref} (db_id,accession) ". 00643 " VALUES (%d, '%s') "; 00644 if(!db_query($dbxref_isql,$db->db_id,$accession)){ 00645 $error .= 'Could not add accession as a database reference '; 00646 } 00647 // get the dbxref_id for the just added accession number 00648 $dbxref_sql = "SELECT dbxref_id FROM {dbxref} ". 00649 "WHERE db_id = %d and accession = '%s'"; 00650 $dbxref = db_fetch_object(db_query($dbxref_sql,$db->db_id,$accession)); 00651 } 00652 00653 00654 // associate the accession number with the feature 00655 $feature_dbxref_isql = "INSERT INTO {feature_dbxref} (feature_id,dbxref_id) ". 00656 " VALUES (%d, %d) "; 00657 if(!db_query($feature_dbxref_isql,$feature_id,$dbxref->dbxref_id)){ 00658 $error .= 'Could not add feature database reference. '; 00659 } 00660 00661 tripal_db_set_active($previous_db); 00662 return $error; 00663 } 00664 00665 /** 00666 * 00667 * 00668 * @ingroup tripal_feature 00669 */ 00670 function chado_feature_form ($node,$param){ 00671 00672 $type = node_get_types('type', $node); 00673 $form = array(); 00674 00675 $feature = $node->feature; 00676 00677 // add the residues to the feature object 00678 $feature = tripal_core_expand_chado_vars($feature,'field','feature.residues'); 00679 00680 // if the node has synonyms then use that as the form may be returning 00681 // from an error. Otherwise try to find synonyms from the database 00682 $synonyms = $node->synonyms; 00683 $feature = tripal_core_expand_chado_vars($feature,'table','feature_synonym'); 00684 $feature_synonyms = $feature->feature_synonym; 00685 if(!$synonyms){ 00686 if (!is_array($feature_synonyms)) { 00687 $synonyms = $feature_synonyms->synonym_id->name; 00688 } 00689 elseif(is_array($feature_synonyms)) { 00690 foreach($feature_synonyms as $index => $synonym){ 00691 $synonyms .= $synonym->synonym_id->name ."\n"; 00692 } 00693 } 00694 } 00695 00696 $analyses = $node->analyses; 00697 $references = $node->references; 00698 00699 // We need to pass above variables for preview to show 00700 $form['feature'] = array( 00701 '#type' => 'value', 00702 '#value' => $feature 00703 ); 00704 // This field is read when previewing a node 00705 $form['synonyms'] = array( 00706 '#type' => 'value', 00707 '#value' => $synonyms 00708 ); 00709 // This field is read when previewing a node 00710 $form['analyses'] = array( 00711 '#type' => 'value', 00712 '#value' => $analyses 00713 ); 00714 // This field is read when previewing a node 00715 $form['references'] = array( 00716 '#type' => 'value', 00717 '#value' => $references 00718 ); 00719 00720 // keep track of the feature id if we have one. If we do have one then 00721 // this would indicate an update as opposed to an insert. 00722 $form['feature_id'] = array( 00723 '#type' => 'value', 00724 '#value' => $feature->feature_id, 00725 ); 00726 00727 $form['title']= array( 00728 '#type' => 'textfield', 00729 '#title' => t('Title'), 00730 '#required' => TRUE, 00731 '#default_value' => $node->title, 00732 '#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.'), 00733 '#weight' => 1, 00734 '#maxlength' => 255 00735 ); 00736 00737 $form['uniquename']= array( 00738 '#type' => 'textfield', 00739 '#title' => t('Unique Feature Name'), 00740 '#required' => TRUE, 00741 '#default_value' => $feature->uniquename, 00742 '#description' => t('Enter a unique name for this feature. This name must be unique for the organism and feature type.'), 00743 '#weight' => 1, 00744 '#maxlength' => 255 00745 ); 00746 00747 $form['fname']= array( 00748 '#type' => 'textfield', 00749 '#title' => t('Feature Name'), 00750 '#required' => TRUE, 00751 '#default_value' => $feature->name, 00752 '#description' => t('Enter the name used by humans to refer to this feature.'), 00753 '#weight' => 1, 00754 '#maxlength' => 255 00755 ); 00756 00757 // get the list of supported feature types 00758 $ftypes = array(); 00759 $ftypes[''] = ''; 00760 $supported_ftypes = split("[ \n]",variable_get('chado_feature_types','EST contig')); 00761 foreach($supported_ftypes as $ftype){ 00762 $ftypes["$ftype"] = $ftype; 00763 } 00764 00765 $form['feature_type'] = array ( 00766 '#title' => t('Feature Type'), 00767 '#type' => t('select'), 00768 '#description' => t("Choose the feature type."), 00769 '#required' => TRUE, 00770 '#default_value' => $feature->type_id->name, 00771 '#options' => $ftypes, 00772 '#weight' => 2 00773 ); 00774 // get the list of organisms 00775 $sql = "SELECT * FROM {Organism} ORDER BY genus, species"; 00776 $previous_db = tripal_db_set_active('chado'); // use chado database 00777 $org_rset = db_query($sql); 00778 tripal_db_set_active($previous_db); // now use drupal database 00779 00780 // 00781 $organisms = array(); 00782 $organisms[''] = ''; 00783 while($organism = db_fetch_object($org_rset)){ 00784 $organisms[$organism->organism_id] = "$organism->genus $organism->species ($organism->common_name)"; 00785 } 00786 00787 $form['organism_id'] = array ( 00788 '#title' => t('Organism'), 00789 '#type' => t('select'), 00790 '#description' => t("Choose the organism with which this feature is associated "), 00791 '#required' => TRUE, 00792 '#default_value' => $feature->organism_id->organism_id, 00793 '#options' => $organisms, 00794 '#weight' => 3, 00795 ); 00796 00797 // Get synonyms 00798 if ($synonyms) { 00799 if (is_array($synonyms)) { 00800 foreach ($synonyms as $synonym){ 00801 $syn_text .= "$synonym->name\n"; 00802 } 00803 } else { 00804 $syn_text = $synonyms; 00805 } 00806 } 00807 $form['synonyms']= array( 00808 '#type' => 'textarea', 00809 '#title' => t('Synonyms'), 00810 '#required' => FALSE, 00811 '#default_value' => $syn_text, 00812 '#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.'), 00813 '#weight' => 5, 00814 ); 00815 00816 $form['residues']= array( 00817 '#type' => 'textarea', 00818 '#title' => t('Residues'), 00819 '#required' => FALSE, 00820 '#default_value' => $feature->residues, 00821 '#description' => t('Enter the nucelotide sequences for this feature'), 00822 '#weight' => 6 00823 ); 00824 00825 $checked = ''; 00826 if($feature->is_obsolete == 't'){ 00827 $checked = '1'; 00828 } 00829 $form['is_obsolete']= array( 00830 '#type' => 'checkbox', 00831 '#title' => t('Is Obsolete'), 00832 '#required' => FALSE, 00833 '#default_value' => $checked, 00834 '#description' => t('Check this box if this sequence should be retired and no longer included in further analysis.'), 00835 '#weight' => 8 00836 ); 00837 return $form; 00838 } 00839 /** 00840 * 00841 * 00842 * @ingroup tripal_feature 00843 */ 00844 function chado_feature_validate($node){ 00845 $result = 0; 00846 00847 // if this is an update, we want to make sure that a different feature for 00848 // the organism doesn't already have this uniquename. We don't want to give 00849 // two sequences the same uniquename 00850 if($node->feature_id){ 00851 $sql = "SELECT * 00852 FROM {Feature} F 00853 INNER JOIN {cvterm} CVT ON F.type_id = CVT.cvterm_id 00854 WHERE uniquename = '%s' 00855 AND organism_id = %d AND CVT.name = '%s' AND NOT feature_id = %d"; 00856 $previous_db = tripal_db_set_active('chado'); 00857 $result = db_fetch_object(db_query($sql, $node->uniquename,$node->organism_id,$node->feature_type,$node->feature_id)); 00858 tripal_db_set_active($previous_db); 00859 if($result){ 00860 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. ")); 00861 } 00862 } 00863 00864 // if this is an insert then we just need to make sure this name doesn't 00865 // already exist for this organism if it does then we need to throw an error 00866 else { 00867 $sql = "SELECT * 00868 FROM {Feature} F 00869 INNER JOIN {cvterm} CVT ON F.type_id = CVT.cvterm_id 00870 WHERE uniquename = '%s' 00871 AND organism_id = %d AND CVT.name = '%s'"; 00872 $previous_db = tripal_db_set_active('chado'); 00873 $result = db_fetch_object(db_query($sql, $node->uniquename,$node->organism_id,$node->feature_type)); 00874 tripal_db_set_active($previous_db); 00875 if($result){ 00876 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. ")); 00877 } 00878 } 00879 00880 // we want to remove all characters except IUPAC nucleotide characters from the 00881 // the residues. however, residues are not required so if blank then we'll skip 00882 // this step 00883 if($node->residues){ 00884 $residues = preg_replace("/[^\w]/",'',$node->residues); 00885 if(!preg_match("/^[ACTGURYMKSWBDHVN]+$/i",$residues)){ 00886 form_set_error('residues',t("The residues in feature $node->name contains more than the nucleotide IUPAC characters. Only the following characters are allowed: A,C,T,G,U,R,Y,M,K,S,W,B,D,H,V,N: '" . $residues ."'")); 00887 } 00888 } 00889 00890 // we don't allow a genbank accession number for a contig 00891 if($node->feature_type == 'contig' and $node->gbaccession){ 00892 form_set_error('gbaccession',t("Contigs cannot have a genbank accession number. Please change the feature type or remove the accession number")); 00893 } 00894 00895 } 00896 /** 00897 * When a node is requested by the user this function is called to allow us 00898 * to add auxiliary data to the node object. 00899 * 00900 * @ingroup tripal_feature 00901 */ 00902 function chado_feature_load($node){ 00903 // get the feature details from chado 00904 $feature_id = chado_get_id_for_node('feature',$node); 00905 00906 $values = array('feature_id' => $feature_id); 00907 $feature = tripal_core_generate_chado_var('feature',$values); 00908 00909 $additions->feature = $feature; 00910 return $additions; 00911 } 00912 /** 00913 * 00914 * 00915 * @ingroup tripal_feature 00916 */ 00917 function tripal_feature_load_organism ($organism_id){ 00918 // add organism details 00919 $sql = "SELECT * FROM {organism} WHERE organism_id = %d"; 00920 $previous_db = tripal_db_set_active('chado'); // use chado database 00921 $organism = db_fetch_object(db_query($sql,$organism_id)); 00922 tripal_db_set_active($previous_db); // now use drupal database 00923 return $organism; 00924 } 00925 /** 00926 * 00927 * 00928 * @ingroup tripal_feature 00929 */ 00930 function tripal_feature_load_synonyms ($feature_id){ 00931 00932 $sql = "SELECT S.name ". 00933 "FROM {Feature_Synonym} FS ". 00934 " INNER JOIN {Synonym} S ". 00935 " ON FS.synonym_id = S.Synonym_id ". 00936 "WHERE FS.feature_id = %d ". 00937 "ORDER BY S.name "; 00938 $previous_db = tripal_db_set_active('chado'); // use chado database 00939 $results = db_query($sql,$feature_id); 00940 tripal_db_set_active($previous_db); // now use drupal database 00941 $synonyms = array(); 00942 $i=0; 00943 while($synonym = db_fetch_object($results)){ 00944 $synonyms[$i++] = $synonym; 00945 } 00946 return $synonyms; 00947 } 00948 /** 00949 * 00950 * 00951 * @ingroup tripal_feature 00952 */ 00953 function tripal_feature_load_properties ($feature_id){ 00954 00955 $sql = "SELECT CVT.name as cvname, FS.type_id, FS.value, FS.rank, 00956 CVT.definition, CVT.is_obsolete, 00957 DBX.dbxref_id,DBX.accession,DB.name as dbname, 00958 DB.urlprefix, DB.description as db_description, DB.url 00959 FROM {featureprop} FS 00960 INNER JOIN {cvterm} CVT ON FS.type_id = CVT.cvterm_id 00961 INNER JOIN {dbxref} DBX ON CVT.dbxref_id = DBX.dbxref_id 00962 INNER JOIN {db} DB ON DB.db_id = DBX.db_id 00963 WHERE FS.feature_id = %d 00964 ORDER BY FS.rank ASC"; 00965 $previous_db = tripal_db_set_active('chado'); // use chado database 00966 $results = db_query($sql,$feature_id); 00967 tripal_db_set_active($previous_db); // now use drupal database 00968 $i=0; 00969 $properties = array(); 00970 while($property = db_fetch_object($results)){ 00971 $properties[$i++] = $property; 00972 } 00973 return $properties; 00974 } 00975 /** 00976 * 00977 * 00978 * @ingroup tripal_feature 00979 */ 00980 function tripal_feature_load_references ($feature_id){ 00981 00982 $sql = "SELECT F.uniquename,F.Feature_id,DBX.accession,DB.description as dbdesc, ". 00983 " DB.db_id, DB.name as db_name, DB.urlprefix,DBX.dbxref_id ". 00984 "FROM {feature} F ". 00985 " INNER JOIN {feature_dbxref} FDBX on F.feature_id = FDBX.feature_id ". 00986 " INNER JOIN {dbxref} DBX on DBX.dbxref_id = FDBX.dbxref_id ". 00987 " INNER JOIN {db} on DB.db_id = DBX.db_id ". 00988 "WHERE F.feature_id = %d ". 00989 "ORDER BY DB.name "; 00990 $previous_db = tripal_db_set_active('chado'); // use chado database 00991 $results = db_query($sql,$feature_id); 00992 tripal_db_set_active($previous_db); // now use drupal database 00993 $references = array(); 00994 $i=0; 00995 while($accession = db_fetch_object($results)){ 00996 $references[$i++] = $accession; 00997 } 00998 return $references; 00999 } 01000 /** 01001 * 01002 * 01003 * @ingroup tripal_feature 01004 */ 01005 function tripal_feature_load_featurelocs ($feature_id,$side = 'as_parent',$aggregate = 1){ 01006 01007 $sql = "SELECT 01008 F.name, F.feature_id, F.uniquename, 01009 FS.name as src_name, 01010 FS.feature_id as src_feature_id, 01011 FS.uniquename as src_uniquename, 01012 CVT.name as cvname, CVT.cvterm_id, 01013 CVTS.name as src_cvname, CVTS.cvterm_id as src_cvterm_id, 01014 FL.fmin, FL.fmax, FL.is_fmin_partial, FL.is_fmax_partial,FL.strand, 01015 FL.phase 01016 FROM {featureloc} FL 01017 INNER JOIN {feature} F on FL.feature_id = F.feature_id 01018 INNER JOIN {feature} FS on FS.feature_id = FL.srcfeature_id 01019 INNER JOIN {cvterm} CVT on F.type_id = CVT.cvterm_id 01020 INNER JOIN {cvterm} CVTS on FS.type_id = CVTS.cvterm_id 01021 "; 01022 if(strcmp($side,'as_parent')==0){ 01023 $sql .= "WHERE FL.srcfeature_id = %d "; 01024 } 01025 if(strcmp($side,'as_child')==0){ 01026 $sql .= "WHERE FL.feature_id = %d "; 01027 } 01028 01029 $previous_db = tripal_db_set_active('chado'); // use chado database 01030 $flresults = db_query($sql, $feature_id); 01031 tripal_db_set_active($previous_db); // now use drupal database 01032 01033 // copy the results into an array 01034 $i=0; 01035 $featurelocs = array(); 01036 while($loc = db_fetch_object($flresults)){ 01037 // if a drupal node exists for this feature then add the nid to the 01038 // results object 01039 $sql = 'SELECT nid FROM {chado_feature} WHERE feature_id = %d'; 01040 01041 $ffeature = db_fetch_object(db_query($sql, $loc->feature_id)); 01042 $sfeature = db_fetch_object(db_query($sql, $loc->src_feature_id)); 01043 $loc->fnid = $ffeature->nid; 01044 $loc->snid = $sfeature->nid; 01045 // add the result to the array 01046 $featurelocs[$i++] = $loc; 01047 } 01048 01049 // Add the relationship feature locs if aggregate is turned on 01050 if($aggregate and strcmp($side,'as_parent')==0){ 01051 // get the relationships for this feature without substituting any children 01052 // for the parent. We want all relationships 01053 $relationships = tripal_feature_get_aggregate_relationships($feature_id,0); 01054 foreach($relationships as $rindex => $rel){ 01055 // get the featurelocs for each of the relationship features 01056 $rel_featurelocs = tripal_feature_load_featurelocs ($rel->subject_id,'as_child',0); 01057 foreach($rel_featurelocs as $findex => $rfloc){ 01058 $featurelocs[$i++] = $rfloc; 01059 } 01060 } 01061 } 01062 01063 usort($featurelocs,'tripal_feature_sort_locations'); 01064 return $featurelocs; 01065 } 01066 /** 01067 * used to sort the feature locs by start position 01068 * 01069 * @ingroup tripal_feature 01070 */ 01071 function tripal_feature_sort_locations($a,$b){ 01072 return strnatcmp($a->fmin, $b->fmin); 01073 } 01074 /** 01075 * 01076 * 01077 * @ingroup tripal_feature 01078 */ 01079 function tripal_feature_load_relationships ($feature_id,$side = 'as_subject'){ 01080 // get the relationships for this feature. The query below is used for both 01081 // querying the object and subject relationships 01082 $sql = "SELECT 01083 FS.name as subject_name, 01084 FS.uniquename as subject_uniquename, 01085 CVTS.name as subject_type, 01086 CVTS.cvterm_id as subject_type_id, 01087 FR.subject_id, 01088 FR.type_id as relationship_type_id, 01089 CVT.name as rel_type, 01090 FO.name as object_name, 01091 FO.uniquename as object_uniquename, 01092 CVTO.name as object_type, 01093 CVTO.cvterm_id as object_type_id, 01094 FR.object_id, 01095 FR.rank 01096 FROM {feature_relationship} FR 01097 INNER JOIN {cvterm} CVT ON FR.type_id = CVT.cvterm_id 01098 INNER JOIN {feature} FS ON FS.feature_id = FR.subject_id 01099 INNER JOIN {feature} FO ON FO.feature_id = FR.object_id 01100 INNER JOIN {cvterm} CVTO ON FO.type_id = CVTO.cvterm_id 01101 INNER JOIN {cvterm} CVTS ON FS.type_id = CVTS.cvterm_id 01102 "; 01103 if(strcmp($side,'as_object')==0){ 01104 $sql .= " WHERE FR.object_id = %d"; 01105 } 01106 if(strcmp($side,'as_subject')==0){ 01107 $sql .= " WHERE FR.subject_id = %d"; 01108 } 01109 $sql .= " ORDER BY FR.rank"; 01110 01111 // get the relationships 01112 $previous_db = tripal_db_set_active('chado'); // use chado database 01113 $results = db_query($sql, $feature_id); 01114 tripal_db_set_active($previous_db); // now use drupal database 01115 01116 01117 // iterate through the relationships, put these in an array and add 01118 // in the Drupal node id if one exists 01119 $i=0; 01120 $nodesql = "SELECT nid FROM {chado_feature} WHERE feature_id = %d"; 01121 $relationships = array(); 01122 while($rel = db_fetch_object($results)){ 01123 $node = db_fetch_object(db_query($nodesql,$rel->subject_id)); 01124 if($node){ 01125 $rel->subject_nid = $node->nid; 01126 } 01127 $node = db_fetch_object(db_query($nodesql,$rel->object_id)); 01128 if($node){ 01129 $rel->object_nid = $node->nid; 01130 } 01131 $relationships[$i++] = $rel; 01132 } 01133 return $relationships; 01134 } 01135 /** 01136 * 01137 * 01138 * @ingroup tripal_feature 01139 */ 01140 function tripal_feature_get_aggregate_types($feature_id){ 01141 // get the feature details 01142 $sql = 'SELECT type_id FROM {feature} WHERE feature_id = %d'; 01143 $previous_db = tripal_db_set_active('chado'); // use chado database 01144 $feature = db_fetch_object(db_query($sql, $feature_id)); 01145 tripal_db_set_active($previous_db); // now use drupal database 01146 01147 // check to see if this feature is of a type with an aggregate 01148 $sql = "SELECT * FROM {tripal_feature_relagg} WHERE type_id = %d"; 01149 $types = array(); 01150 $results = db_query($sql,$feature->type_id); 01151 while($agg = db_fetch_object($results)){ 01152 $types[] = $agg->rel_type_id; 01153 } 01154 01155 return $types; 01156 } 01157 /** 01158 * 01159 * 01160 * @ingroup tripal_feature 01161 */ 01162 function tripal_feature_get_aggregate_relationships($feature_id, $substitute=1, 01163 $levels=0, $base_type_id=NULL, $depth=0) 01164 { 01165 01166 // we only want to recurse to as many levels deep as indicated by the 01167 // $levels variable, but only if this variable is > 0. If 0 then we 01168 // recurse until we reach the end of the relationships tree. 01169 if($levels > 0 and $levels == $depth){ 01170 return NULL; 01171 } 01172 01173 // first get the relationships for this feature 01174 $relationships = tripal_feature_load_relationships($feature_id,'as_object'); 01175 01176 // next, iterate through these relationships and descend, adding in those 01177 // that are specified by the aggregator. 01178 $i=0; 01179 $new_relationships = array(); 01180 foreach($relationships as $rindex => $rel){ 01181 01182 // set the base type id 01183 if(!$base_type_id){ 01184 $base_type_id = $rel->object_type_id; 01185 } 01186 // check to see if we have an aggregator for this base type 01187 $sql = "SELECT * FROM {tripal_feature_relagg} WHERE type_id = %d and rel_type_id = %d"; 01188 $agg = db_fetch_object(db_query($sql,$base_type_id,$rel->subject_type_id)); 01189 if($agg){ 01190 // if we're not going to substitute the resulting relationships for the 01191 // parent then we need to add the parent to our list 01192 if(!$substitute){ 01193 $new_relationships[$i++] = $rel; 01194 } 01195 // recurse all relationships 01196 $agg_relationships = tripal_feature_get_aggregate_relationships( 01197 $rel->subject_id,$levels,$base_type_id,$depth++); 01198 // if we have an aggregate defined but we have no relationships beyond 01199 // this point then there's nothing we can substitute 01200 if(!$agg_relationships and $substitute){ 01201 $new_relationships[$i++] = $rel; 01202 } 01203 01204 // merge all relationships into one array 01205 foreach($agg_relationships as $aindex => $arel){ 01206 $new_relationships[$i++] = $arel; 01207 } 01208 } 01209 else { 01210 // if we don't have an aggregate then keep the current relationship 01211 $new_relationships[$i++] = $rel; 01212 } 01213 } 01214 return $new_relationships; 01215 } 01216 /** 01217 * 01218 * 01219 * @ingroup tripal_feature 01220 */ 01221 function tripal_feature_load_featureloc_sequences($feature_id,$featurelocs){ 01222 01223 // if we don't have any featurelocs then no point in continuing 01224 if(!$featurelocs){ 01225 return array(); 01226 } 01227 01228 // get the list of relationships (including any aggregators) and iterate 01229 // through each one to find information needed to color-code the reference sequence 01230 $relationships = tripal_feature_get_aggregate_relationships($feature_id); 01231 if(!$relationships){ 01232 return array(); 01233 } 01234 01235 01236 // iterate through each of the realtionships features and get their 01237 // locations 01238 foreach($relationships as $rindex => $rel){ 01239 // get the featurelocs for each of the relationship features 01240 $rel_featurelocs = tripal_feature_load_featurelocs ($rel->subject_id,'as_child',0); 01241 foreach($rel_featurelocs as $rfindex => $rel_featureloc){ 01242 // keep track of this unique source feature 01243 $src = $rel_featureloc->src_feature_id ."-". $rel_featureloc->src_cvterm_id; 01244 01245 // copy over the results to the relationship object. Since there can 01246 // be more than one feature location for each relationship feature we 01247 // use the '$src' variable to keep track of these. 01248 $rel->featurelocs->$src->src_uniquename = $rel_featureloc->src_uniquename; 01249 $rel->featurelocs->$src->src_cvterm_id = $rel_featureloc->src_cvterm_id; 01250 $rel->featurelocs->$src->src_cvname = $rel_featureloc->src_cvname; 01251 $rel->featurelocs->$src->fmin = $rel_featureloc->fmin; 01252 $rel->featurelocs->$src->fmax = $rel_featureloc->fmax; 01253 $rel->featurelocs->$src->src_name = $rel_featureloc->src_name; 01254 01255 // keep track of the individual parts for each relationship 01256 $start = $rel->featurelocs->$src->fmin; 01257 $end = $rel->featurelocs->$src->fmax; 01258 $rel_locs[$src]['parts'][$start]['type'] = $rel->subject_type; 01259 $rel_locs[$src]['parts'][$start]['start'] = $start; 01260 $rel_locs[$src]['parts'][$start]['end'] = $end; 01261 } 01262 } 01263 01264 // the featurelocs array provided to the function contains the locations 01265 // where this feature is found. We want to get the sequence for each 01266 // location and then annotate it with the parts found from the relationships 01267 // locations determiend above. 01268 $sql = "SELECT residues FROM {feature} WHERE feature_id = %d"; 01269 $floc_sequences = array(); 01270 foreach ($featurelocs as $featureloc){ 01271 // get the residues for this feature 01272 $previous_db = tripal_db_set_active('chado'); // use chado database 01273 $feature = db_fetch_object(db_query($sql,$featureloc->srcfeature_id->feature_id)); 01274 tripal_db_set_active($previous_db); // now use drupal database 01275 01276 $src = $featureloc->srcfeature_id->feature_id ."-". $featureloc->srcfeature_id->type_id->cvterm_id; 01277 01278 // orient the parts to the beginning of the feature sequence 01279 $parts = $rel_locs[$src]['parts']; 01280 usort($parts, 'tripal_feature_sort_rel_parts'); 01281 foreach ($parts as $start => $attrs){ 01282 $parts[$start]['start'] = $parts[$start]['start'] - $featureloc->fmin; 01283 $parts[$start]['end'] = $parts[$start]['end'] - $featureloc->fmin; 01284 } 01285 $floc_sequences[$src]['src'] = $src; 01286 $floc_sequences[$src]['type'] = $featureloc->feature_id->type_id->name; 01287 $sequence = substr($feature->residues,$featureloc->fmin-1,($featureloc->fmax - $featureloc->fmin)+1); 01288 $floc_sequences[$src]['formatted_seq'] = tripal_feature_color_sequence ( 01289 $sequence,$parts); 01290 } 01291 return $floc_sequences; 01292 } 01293 /** 01294 * 01295 * 01296 * @ingroup tripal_feature 01297 */ 01298 function tripal_feature_load_organism_feature_counts($organism){ 01299 01300 // don't show the browser if the settings in the admin page is turned off 01301 // instead return the array indicating the status of the browser 01302 $show_counts = variable_get('tripal_feature_summary_setting','show_feature_summary'); 01303 if(strcmp($show_counts,'show_feature_summary')!=0){ 01304 return array ('enabled' => false ); 01305 } 01306 01307 // get the feature counts. This is dependent on a materialized view 01308 // installed with the organism module 01309 $sql = " 01310 SELECT OFC.num_features,OFC.feature_type,CVT.definition 01311 FROM {organism_feature_count} OFC 01312 INNER JOIN {cvterm} CVT on OFC.cvterm_id = CVT.cvterm_id 01313 WHERE organism_id = %d 01314 ORDER BY num_features desc 01315 "; 01316 $previous_db = tripal_db_set_active('chado'); // use chado database 01317 $org_features = db_query($sql,$organism->organism_id); 01318 tripal_db_set_active($previous_db); // now use drupal database 01319 01320 $i=0; 01321 $types = array(); 01322 while($type = db_fetch_object($org_features)){ 01323 $types[$i++] = $type; 01324 } 01325 return array ( 'types' => $types, 'enabled' => true ); 01326 } 01327 /** 01328 * 01329 * 01330 * @ingroup tripal_feature 01331 */ 01332 function tripal_feature_load_organism_feature_browser($organism){ 01333 01334 // don't show the browser if the settings in the admin page is turned off 01335 // instead return the array indicating the status of the browser 01336 $show_browser = variable_get('tripal_feature_browse_setting','show_feature_browser'); 01337 if(strcmp($show_browser,'show_feature_browser')!=0){ 01338 return array ('enabled' => false); 01339 } 01340 01341 # get the list of available sequence ontology terms for which 01342 # we will build drupal pages from features in chado. If a feature 01343 # is not one of the specified typse we won't build a node for it. 01344 $allowed_types = variable_get('chado_feature_types','EST contig'); 01345 $allowed_types = preg_replace("/[\s\n\r]+/"," ",$allowed_types); 01346 $so_terms = split(' ',$allowed_types); 01347 $where_cvt = ""; 01348 foreach ($so_terms as $term){ 01349 $where_cvt .= "CVT.name = '$term' OR "; 01350 } 01351 $where_cvt = substr($where_cvt,0,strlen($where_cvt)-3); # strip trailing 'OR' 01352 01353 // get the features for this organism 01354 $sql = "SELECT F.name,F.feature_id,F.uniquename,CVT.name as cvname ". 01355 "FROM {feature} F ". 01356 " INNER JOIN {cvterm} CVT on F.type_id = CVT.cvterm_id ". 01357 "WHERE organism_id = %s and ($where_cvt) ". 01358 "ORDER BY feature_id ASC"; 01359 01360 // the counting SQL 01361 $csql = "SELECT count(*) ". 01362 "FROM {feature} F". 01363 " INNER JOIN {cvterm} CVT on F.type_id = CVT.cvterm_id ". 01364 "WHERE organism_id = %s and ($where_cvt) ". 01365 "GROUP BY organism_id "; 01366 01367 $previous_db = tripal_db_set_active('chado'); // use chado database 01368 $org_features = pager_query($sql,10,0,$csql,$organism->organism_id); 01369 tripal_db_set_active($previous_db); // now use drupal database 01370 $pager = theme('pager'); 01371 01372 // prepare the query that will lookup node ids 01373 $sql = "SELECT nid FROM {chado_feature} ". 01374 "WHERE feature_id = %d"; 01375 $i=0; 01376 $features = array(); 01377 while($feature = db_fetch_object($org_features)){ 01378 $node = db_fetch_object(db_query($sql,$feature->feature_id)); 01379 $feature->nid = $node->nid; 01380 $features[$i++] = $feature; 01381 } 01382 01383 return array ( 'features' => $features, 'pager' => $pager, 'enabled' => true ); 01384 } 01385 01386 /** 01387 * used to sort the list of relationship objects by start position 01388 * 01389 * @ingroup tripal_feature 01390 */ 01391 function tripal_feature_sort_rel_objects($a,$b){ 01392 return strnatcmp($a->fmin, $b->fmin); 01393 } 01394 01395 /** 01396 * used to sort the list of relationship parts by start position 01397 * 01398 * @ingroup tripal_feature 01399 */ 01400 function tripal_feature_sort_rel_parts($a,$b){ 01401 return strnatcmp($a['start'], $b['start']); 01402 } 01403 01404 /** 01405 * 01406 * 01407 * @ingroup tripal_feature 01408 */ 01409 function tripal_feature_color_sequence ($sequence,$parts){ 01410 01411 $types = array(); 01412 01413 // first get the list of types so we can create a color legend 01414 foreach ($parts as $index => $child){ 01415 $type = $child['type']; 01416 if(!in_array($type,$types)){ 01417 $types[] = $type; 01418 } 01419 } 01420 01421 $newseq .= "<div id=\"tripal_feature-featureloc_sequence-legend\">Legend: "; 01422 foreach($types as $type){ 01423 $newseq .= "<span class=\"tripal_feature-featureloc_sequence-$type\">$type</span>"; 01424 } 01425 $newseq .= "</div>"; 01426 01427 01428 // set the background color of the rows based on the type 01429 $pos = 0; 01430 $newseq .= "<pre id=\"tripal_feature-featureloc_sequence\">"; 01431 foreach ($parts as $index => $child){ 01432 $type = $child['type']; 01433 $start = $child['start']; 01434 $end = $child['end']+1; 01435 01436 $class = "class=\"tripal_feature-featureloc_sequence-$type\""; 01437 01438 // iterate through the sequence up to the end of the child 01439 for ($i = $pos; $i < $end; $i++){ 01440 01441 // if we're at the beginning of the child sequence then set the 01442 // appropriate text color 01443 if($pos == $start){ 01444 $newseq .= "<span $class>"; 01445 $func = 'uc'; // nucleotides within the child should be uppercase 01446 } 01447 $newseq .= $sequence{$pos}; 01448 $seqcount++; 01449 01450 if($seqcount % 60 == 0){ 01451 $newseq .= "\n"; 01452 } 01453 $pos++; 01454 if($pos == $end){ 01455 $newseq .= "</span>"; 01456 $func = 'lc'; 01457 } 01458 } 01459 } 01460 01461 $newseq .= "</pre>"; 01462 return $newseq; 01463 } 01464 01465 /** 01466 * This function customizes the view of the chado_feature node. It allows 01467 * us to generate the markup. 01468 * 01469 * @ingroup tripal_feature 01470 */ 01471 function chado_feature_view ($node, $teaser = FALSE, $page = FALSE) { 01472 01473 if (!$teaser) { 01474 // use drupal's default node view: 01475 $node = node_prepare($node, $teaser); 01476 01477 // if we're building the node for searching then 01478 // we want to handle this within the module and 01479 // not allow theme customization. We don't want to 01480 // index all items (such as DNA sequence). 01481 if($node->build_mode == NODE_BUILD_SEARCH_INDEX){ 01482 $node->content['index_version'] = array( 01483 '#value' => theme('tripal_feature_search_index',$node), 01484 '#weight' => 1, 01485 ); 01486 } 01487 elseif($node->build_mode == NODE_BUILD_SEARCH_RESULT){ 01488 $node->content['index_version'] = array( 01489 '#value' => theme('tripal_feature_search_results',$node), 01490 '#weight' => 1, 01491 ); 01492 } 01493 else { 01494 // do nothing here, let the theme derived template handle display 01495 } 01496 } 01497 01498 return $node; 01499 } 01500 01501 /** 01502 * Display feature information for associated organisms. This function also 01503 * provides contents for indexing 01504 * 01505 * @ingroup tripal_feature 01506 */ 01507 function tripal_feature_nodeapi(&$node, $op, $teaser, $page) { 01508 01509 switch ($op) { 01510 // Note that this function only adds feature view to an organism node. 01511 // The view of a feature node is controled by the theme *.tpl file 01512 case 'view': 01513 switch($node->type){ 01514 case 'chado_organism': 01515 // Show feature browser 01516 $types_to_show = array('chado_organism', 'chado_library'); 01517 if (in_array($node->type, $types_to_show, TRUE)) { 01518 $node->content['tripal_organism_feature_counts'] = array( 01519 '#value' => theme('tripal_organism_feature_counts', $node), 01520 ); 01521 $node->content['tripal_organism_feature_browser'] = array( 01522 '#value' => theme('tripal_organism_feature_browser', $node), 01523 ); 01524 } 01525 break; 01526 case 'chado_library': 01527 break; 01528 default: 01529 } 01530 break; 01531 } 01532 } 01533 01534 /** 01535 * We need to let drupal know about our theme functions and their arguments. 01536 * We create theme functions to allow users of the module to customize the 01537 * look and feel of the output generated in this module 01538 * 01539 * @ingroup tripal_feature 01540 */ 01541 function tripal_feature_theme () { 01542 return array( 01543 'tripal_feature_search_index' => array ( 01544 'arguments' => array('node'), 01545 ), 01546 'tripal_feature_search_results' => array ( 01547 'arguments' => array('node'), 01548 ), 01549 'tripal_organism_feature_browser' => array ( 01550 'arguments' => array('node'=> null), 01551 'template' => 'tripal_organism_feature_browser', 01552 ), 01553 'tripal_organism_feature_counts' => array ( 01554 'arguments' => array('node'=> null), 01555 'template' => 'tripal_organism_feature_counts', 01556 ), 01557 'tripal_feature_base' => array ( 01558 'arguments' => array('node'=> null), 01559 'template' => 'tripal_feature_base', 01560 ), 01561 'tripal_feature_sequence' => array ( 01562 'arguments' => array('node'=> null), 01563 'template' => 'tripal_feature_sequence', 01564 ), 01565 'tripal_feature_synonyms' => array ( 01566 'arguments' => array('node'=> null), 01567 'template' => 'tripal_feature_synonyms', 01568 ), 01569 'tripal_feature_featureloc_sequences' => array ( 01570 'arguments' => array('node'=> null), 01571 'template' => 'tripal_feature_featureloc_sequences', 01572 ), 01573 'tripal_feature_references' => array ( 01574 'arguments' => array('node'=> null), 01575 'template' => 'tripal_feature_references', 01576 ), 01577 'tripal_feature_properties' => array ( 01578 'arguments' => array('node'=> null), 01579 'template' => 'tripal_feature_properties', 01580 ), 01581 'tripal_feature_featurelocs' => array ( 01582 'arguments' => array('node'=> null), 01583 'template' => 'tripal_feature_featurelocs', 01584 ), 01585 'tripal_feature_relationships' => array ( 01586 'arguments' => array('node'=> null), 01587 'template' => 'tripal_feature_relationships', 01588 ), 01589 ); 01590 } 01591 01592 01593 /** 01594 * 01595 * 01596 * @ingroup tripal_feature 01597 */ 01598 function tripal_feature_preprocess_tripal_organism_feature_counts(&$variables){ 01599 $organism = $variables['node']->organism; 01600 $organism->feature_counts = tripal_feature_load_organism_feature_counts($organism); 01601 } 01602 01603 /** 01604 * 01605 * 01606 * @ingroup tripal_feature 01607 */ 01608 function tripal_feature_preprocess_tripal_organism_feature_browser(&$variables){ 01609 $organism = $variables['node']->organism; 01610 $organism->feature_browser = tripal_feature_load_organism_feature_browser($organism); 01611 } 01612 01613 01614 /** 01615 * 01616 * 01617 * @ingroup tripal_feature 01618 */ 01619 function tripal_feature_cv_chart($chart_id){ 01620 01621 // The CV module will create the JSON array necessary for buillding a 01622 // pie chart using jgChart and Google Charts. We have to pass to it 01623 // a table that contains count information, tell it which column 01624 // contains the cvterm_id and provide a filter for getting the 01625 // results we want from the table. 01626 $organism_id = preg_replace("/^tripal_feature_cv_chart_(\d+)$/","$1",$chart_id); 01627 $options = array( 01628 count_mview => 'organism_feature_count', 01629 cvterm_id_column => 'cvterm_id', 01630 count_column => 'num_features', 01631 size => '550x200', 01632 filter => "CNT.organism_id = $organism_id", 01633 ); 01634 return $options; 01635 } 01636 01637 /** 01638 * 01639 * 01640 * @ingroup tripal_feature 01641 */ 01642 function tripal_feature_cv_tree($tree_id){ 01643 01644 // The CV module will create the JSON array necessary for buillding a 01645 // pie chart using jgChart and Google Charts. We have to pass to it 01646 // a table that contains count information, tell it which column 01647 // contains the cvterm_id and provide a filter for getting the 01648 // results we want from the table. 01649 $organism_id = preg_replace("/^tripal_feature_cv_tree_(\d+)$/","$1",$tree_id); 01650 $options = array( 01651 cv_id => tripal_cv_get_cv_id('sequence'), 01652 count_mview => 'organism_feature_count', 01653 cvterm_id_column => 'cvterm_id', 01654 count_column => 'num_features', 01655 filter => "CNT.organism_id = $organism_id", 01656 label => 'Features', 01657 ); 01658 return $options; 01659 } 01660 01661 /** 01662 * This function is an extension of the chado_feature_view by providing 01663 * the markup for the feature object THAT WILL BE INDEXED. 01664 * 01665 * @ingroup tripal_feature 01666 */ 01667 function theme_tripal_feature_search_index ($node) { 01668 $feature = $node->feature; 01669 $content = ''; 01670 01671 // get the accession prefix 01672 $aprefix = variable_get('chado_feature_accession_prefix','ID'); 01673 01674 $content .= "<h1>$feature->uniquename</h1>. "; 01675 $content .= "<strong>$aprefix$feature->feature_id.</strong> "; 01676 $content .= "$feature->cvname "; 01677 $content .= "$feature->common_name "; 01678 01679 // add the synonyms of this feature to the text for searching 01680 $synonyms = $node->synonyms; 01681 if(count($synonyms) > 0){ 01682 foreach ($synonyms as $result){ 01683 $content .= "$result->name "; 01684 } 01685 } 01686 01687 return $content; 01688 } 01689 01690 /** 01691 * This function is an extension of the chado_feature_view by providing 01692 * the markup for the feature object THAT WILL BE INDEXED. 01693 * 01694 * @ingroup tripal_feature 01695 */ 01696 function theme_tripal_feature_search_results ($node) { 01697 $feature = $node->feature; 01698 $content = ''; 01699 01700 // get the accession prefix 01701 $aprefix = variable_get('chado_feature_accession_prefix','ID'); 01702 01703 $content .= "Feature Name: <h1>$feature->uniquename</h1>. "; 01704 $content .= "<strong>Accession: $aprefix$feature->feature_id.</strong>"; 01705 $content .= "Type: $feature->cvname. "; 01706 $content .= "Organism: $feature->common_name. "; 01707 01708 // add the synonyms of this feature to the text for searching 01709 $synonyms = $node->synonyms; 01710 if(count($synonyms) > 0){ 01711 $content .= "Synonyms: "; 01712 foreach ($synonyms as $result){ 01713 $content .= "$result->name, "; 01714 } 01715 } 01716 01717 return $content; 01718 } 01719 01720 /** 01721 * 01722 * 01723 * @ingroup tripal_feature 01724 */ 01725 function tripal_feature_set_vocabulary (){ 01726 01727 //include the file containing the required functions for adding taxonomy vocabs 01728 module_load_include('inc', 'taxonomy', 'taxonomy.admin'); 01729 01730 // get the vocabularies so that we make sure we don't recreate 01731 // the vocabs that already exist 01732 $vocabularies = taxonomy_get_vocabularies(); 01733 $ft_vid = NULL; 01734 $op_vid = NULL; 01735 $lb_vid = NULL; 01736 $an_vid = NULL; 01737 01738 // These taxonomic terms are hard coded because we 01739 // konw we have these relationships in the chado tables 01740 // through foreign key relationships. The tripal 01741 // modules that correspond to these chado "modules" don't 01742 // need to be installed for the taxonomy to work. 01743 foreach($vocabularies as $vocab){ 01744 if($vocab->name == 'Feature Type'){ 01745 $ft_vid = $vocab->vid; 01746 } 01747 if($vocab->name == 'Organism'){ 01748 $op_vid = $vocab->vid; 01749 } 01750 if($vocab->name == 'Library'){ 01751 $lb_vid = $vocab->vid; 01752 } 01753 if($vocab->name == 'Analysis'){ 01754 $an_vid = $vocab->vid; 01755 } 01756 } 01757 01758 if(!$ft_vid){ 01759 $form_state = array(); 01760 $values = array( 01761 'name' => t('Feature Type'), 01762 'nodes' => array('chado_feature' => 'chado_feature'), 01763 'description' => t('The feature type (or SO cvterm for this feature).'), 01764 'help' => t('Select the term that matches the feature '), 01765 'tags' => 0, 01766 'hierarchy' => 1, 01767 'relations' => 1, 01768 'multiple' => 0, 01769 'required' => 0, 01770 'weight' => 1, 01771 ); 01772 drupal_execute('taxonomy_form_vocabulary', $form_state,$values); 01773 drupal_execute('taxonomy_form_vocabulary', $form_state); 01774 } 01775 01776 if(!$op_vid){ 01777 $form_state = array(); 01778 $values = array( 01779 'name' => t('Organism'), 01780 'nodes' => array('chado_feature' => 'chado_feature'), 01781 'description' => t('The organism to which this feature belongs.'), 01782 'help' => t('Select the term that matches the feature '), 01783 'tags' => 0, 01784 'hierarchy' => 1, 01785 'relations' => 1, 01786 'multiple' => 0, 01787 'required' => 0, 01788 'weight' => 2, 01789 ); 01790 drupal_execute('taxonomy_form_vocabulary', $form_state,$values); 01791 drupal_execute('taxonomy_form_vocabulary', $form_state); 01792 } 01793 01794 if(!$lb_vid){ 01795 $form_state = array(); 01796 $values = array( 01797 'name' => t('Library'), 01798 'nodes' => array('chado_feature' => 'chado_feature'), 01799 'description' => t('Chado features associated with a library are assigned the term associated with the library'), 01800 'help' => t('Select the term that matches the feature '), 01801 'tags' => 0, 01802 'hierarchy' => 1, 01803 'relations' => 1, 01804 'multiple' => 0, 01805 'required' => 0, 01806 'weight' => 3, 01807 ); 01808 drupal_execute('taxonomy_form_vocabulary', $form_state, $values); 01809 drupal_execute('taxonomy_form_vocabulary', $form_state); 01810 } 01811 01812 if(!$an_vid){ 01813 $form_state = array(); 01814 $values = array( 01815 'name' => t('Analysis'), 01816 'nodes' => array('chado_feature' => 'chado_feature'), 01817 'description' => t('Any analysis to which this feature belongs.'), 01818 'help' => t('Select the term that matches the feature '), 01819 'tags' => 0, 01820 'hierarchy' => 1, 01821 'relations' => 1, 01822 'multiple' => 1, 01823 'required' => 0, 01824 'weight' => 4, 01825 ); 01826 drupal_execute('taxonomy_form_vocabulary', $form_state,$values); 01827 drupal_execute('taxonomy_form_vocabulary', $form_state); 01828 } 01829 } 01830 01831 /** 01832 * 01833 * 01834 * @ingroup tripal_feature 01835 */ 01836 function tripal_feature_del_vocabulary(){ 01837 //include the file containing the required functions for adding taxonomy vocabs 01838 module_load_include('inc', 'taxonomy', 'taxonomy.admin'); 01839 01840 // get the vocabularies 01841 $vocabularies = taxonomy_get_vocabularies(); 01842 01843 // These taxonomic terms are hard coded because we 01844 // know we have these relationships in the chado tables 01845 // through foreign key relationships. The tripal 01846 // modules that correspond to these chado "modules" don't 01847 // need to be installed for the taxonomy to work. 01848 foreach($vocabularies as $vocab){ 01849 if($vocab->name == 'Feature Type'){ 01850 taxonomy_del_vocabulary($vocab->vid); 01851 } 01852 if($vocab->name == 'Organism'){ 01853 taxonomy_del_vocabulary($vocab->vid); 01854 } 01855 if($vocab->name == 'Library'){ 01856 taxonomy_del_vocabulary($vocab->vid); 01857 } 01858 if($vocab->name == 'Analysis'){ 01859 taxonomy_del_vocabulary($vocab->vid); 01860 } 01861 } 01862 01863 } 01864 01865 /** 01866 * 01867 * 01868 * @ingroup tripal_feature 01869 */ 01870 function tripal_features_set_taxonomy($max_sync = 0,$job_id = NULL){ 01871 01872 // make sure our vocabularies are cleaned and reset before proceeding 01873 tripal_feature_del_vocabulary(); 01874 tripal_feature_set_vocabulary(); 01875 01876 // iterate through all drupal feature nodes and set the taxonomy 01877 $results = db_query("SELECT * FROM {chado_feature}"); 01878 $nsql = "SELECT * FROM {node} ". 01879 "WHERE nid = %d"; 01880 $i = 0; 01881 01882 // load into ids array 01883 $count = 0; 01884 $chado_features = array(); 01885 while($chado_feature = db_fetch_object($results)){ 01886 $chado_features[$count] = $chado_feature; 01887 $count++; 01888 } 01889 01890 // Iterate through features that need to be synced 01891 $interval = intval($count * 0.01); 01892 foreach($chado_features as $chado_feature){ 01893 01894 // update the job status every 1% features 01895 if($job_id and $i % $interval == 0){ 01896 tripal_job_set_progress($job_id,intval(($i/$count)*100)); 01897 } 01898 print "$i of $count: "; 01899 $node = db_fetch_object(db_query($nsql,$chado_feature->nid)); 01900 tripal_feature_set_taxonomy($node,$chado_feature->feature_id); 01901 01902 $i++; 01903 } 01904 } 01905 01906 /** 01907 * 01908 * 01909 * @ingroup tripal_feature 01910 */ 01911 function tripal_feature_set_taxonomy ($node,$feature_id){ 01912 01913 // iterate through the taxonomy classes that have been 01914 // selected by the admin user and make sure we only set those 01915 $tax_classes = variable_get('tax_classes', ''); 01916 $do_ft = 0; 01917 $do_op = 0; 01918 $do_lb = 0; 01919 $do_an = 0; 01920 foreach($tax_classes as $class){ 01921 if(strcmp($class ,'organism')==0){ 01922 $do_op = 1; 01923 } 01924 if(strcmp($class,'feature_type')==0){ 01925 $do_ft = 1; 01926 } 01927 if(strcmp($class,'library')==0){ 01928 $do_lb = 1; 01929 } 01930 if(strcmp($class,'analysis')==0){ 01931 $do_an = 1; 01932 } 01933 } 01934 01935 01936 // get the list of vocabularies and find our two vocabularies of interest 01937 $vocabularies = taxonomy_get_vocabularies(); 01938 $ft_vid = NULL; 01939 $op_vid = NULL; 01940 $lb_vid = NULL; 01941 $an_vid = NULL; 01942 foreach($vocabularies as $vocab){ 01943 if($vocab->name == 'Feature Type'){ 01944 $ft_vid = $vocab->vid; 01945 } 01946 if($vocab->name == 'Organism'){ 01947 $op_vid = $vocab->vid; 01948 } 01949 if($vocab->name == 'Library'){ 01950 $lb_vid = $vocab->vid; 01951 } 01952 if($vocab->name == 'Analysis'){ 01953 $an_vid = $vocab->vid; 01954 } 01955 } 01956 01957 // get the cvterm and the organism for this feature 01958 $sql = "SELECT CVT.name AS cvname, O.genus, O.species ". 01959 "FROM {CVTerm} CVT ". 01960 " INNER JOIN Feature F on F.type_id = CVT.cvterm_id ". 01961 " INNER JOIN Organism O ON F.organism_id = O.organism_id ". 01962 "WHERE F.feature_id = $feature_id"; 01963 $previous_db = tripal_db_set_active('chado'); // use chado database 01964 $feature = db_fetch_object(db_query($sql)); 01965 tripal_db_set_active($previous_db); // now use drupal database 01966 01967 // Set the feature type for this feature 01968 if($do_ft && $ft_vid){ 01969 $tags["$ft_vid"] = "$feature->cvname"; 01970 } 01971 // Set the organism for this feature type 01972 if($do_op && $op_vid){ 01973 $tags["$op_vid"] = "$feature->genus $feature->species"; 01974 } 01975 01976 // get the library that this feature may belong to and add it as taxonomy 01977 if($do_lb && $lb_vid){ 01978 $sql = "SELECT L.name ". 01979 "FROM {Library} L ". 01980 " INNER JOIN Library_feature LF ON LF.library_id = L.library_id ". 01981 "WHERE LF.feature_id = %d "; 01982 $previous_db = tripal_db_set_active('chado'); // use chado database 01983 $library = db_fetch_object(db_query($sql,$feature_id)); 01984 tripal_db_set_active($previous_db); // now use drupal database 01985 $tags["$lb_vid"] = "$library->name"; 01986 } 01987 01988 // now add the taxonomy to the node 01989 $terms['tags'] = $tags; 01990 taxonomy_node_save($node,$terms); 01991 // print "Setting $node->name: " . implode(", ",$tags) . "\n"; 01992 01993 // get the analysis that this feature may belong to and add it as taxonomy 01994 // We'll add each one individually since there may be more than one analysis 01995 if($do_an && $an_vid){ 01996 $sql = "SELECT A.name ". 01997 "FROM {Analysis} A ". 01998 " INNER JOIN Analysisfeature AF ON AF.analysis_id = A.analysis_id ". 01999 "WHERE AF.feature_id = $feature_id "; 02000 $results = db_query($sql); 02001 $previous_db = tripal_db_set_active('chado'); // use chado database 02002 $analysis_terms = array(); 02003 while($analysis=db_fetch_object($results)){ 02004 $tags2["$an_vid"] = "$analysis->name"; 02005 $terms['tags'] = $tags2; 02006 taxonomy_node_save($node,$terms); 02007 } 02008 tripal_db_set_active($previous_db); // now use drupal database 02009 } 02010 02011 } 02012 02013 /** 02014 * 02015 * 02016 * @ingroup tripal_feature 02017 */ 02018 function tripal_features_cleanup($dummy = NULL, $job_id = NULL) { 02019 02020 // build the SQL statments needed to check if nodes point to valid features 02021 $dsql = "SELECT * FROM {node} WHERE type = 'chado_feature' order by nid"; 02022 $nsql = "SELECT * FROM {node} WHERE nid = %d"; 02023 $csql = "SELECT * FROM {chado_feature} where nid = %d "; 02024 $cfsql= "SELECT * FROM {chado_feature}"; 02025 $tsql = "SELECT * FROM {feature} F ". 02026 " INNER JOIN CVTerm CVT ON F.type_id = CVT.cvterm_id ". 02027 "WHERE feature_id = %d AND ("; 02028 $supported_ftypes = split("[ \n]",variable_get('chado_feature_types','EST contig')); 02029 foreach($supported_ftypes as $ftype){ 02030 $tsql .= " CVT.name = '$ftype' OR "; 02031 } 02032 $tsql .= " 0=1) "; // add a 0=1 just as a filler so we don't have to remove a trailing 'OR' 02033 02034 // load into nodes array 02035 $results = db_query($dsql); 02036 $count = 0; 02037 $nodes = array(); 02038 while($node = db_fetch_object($results)){ 02039 $nodes[$count] = $node; 02040 $count++; 02041 } 02042 02043 // load the chado_features into an array 02044 $results = db_query($cfsql); 02045 $cnodes = array(); 02046 while($node = db_fetch_object($results)){ 02047 $cnodes[$count] = $node; 02048 $count++; 02049 } 02050 $interval = intval($count * 0.01); 02051 02052 // iterate through all of the chado_feature nodes and delete those that aren't valid 02053 foreach($nodes as $nid){ 02054 02055 // update the job status every 1% features 02056 if($job_id and $i % $interval == 0){ 02057 tripal_job_set_progress($job_id,intval(($i/$count)*100)); 02058 } 02059 02060 // first check to see if the node has a corresponding entry 02061 // in the chado_feature table. If not then delete the node. 02062 $feature = db_fetch_object(db_query($csql,$nid->nid)); 02063 if(!$feature){ 02064 node_delete($nid->nid); 02065 $message = "Missing in chado_feature table.... DELETING: $nid->nid\n"; 02066 watchdog('tripal_feature',$message,array(),WATCHDOG_WARNING); 02067 continue; 02068 } 02069 02070 // second check to see if the node is for a feature of an allowed type. 02071 // if not, then delete the node. This check will also take care of the 02072 // case when a node exists and an entry in the chado_feature table exists 02073 // but no feature with a matching feature_id exists 02074 $previous_db = tripal_db_set_active('chado'); // use chado database 02075 $ftype = db_fetch_object(db_query($tsql,$feature->feature_id)); 02076 tripal_db_set_active($previous_db); // now use drupal database 02077 02078 if(!$ftype){ 02079 node_delete($nid->nid); 02080 db_query("DELETE FROM {chado_feature} WHERE feature_id = $feature->feature_id"); 02081 $message = "Node of the wrong feature type.... DELETING: $nid->nid\n"; 02082 watchdog('tripal_feature',$message,array(),WATCHDOG_WARNING); 02083 } 02084 $i++; 02085 } 02086 02087 // iterate through all of the chado_feature nodes and delete those that aren't valid 02088 foreach($cnodes as $nid){ 02089 // update the job status every 1% features 02090 if($job_id and $i % $interval == 0){ 02091 tripal_job_set_progress($job_id,intval(($i/$count)*100)); 02092 } 02093 $node = db_fetch_object(db_query($nsql,$nid->nid)); 02094 if(!$node){ 02095 db_query("DELETE FROM {chado_feature} WHERE nid = $nid->nid"); 02096 $message = "chado_feature missing node.... DELETING: $nid->nid\n"; 02097 watchdog('tripal_feature',$message,array(),WATCHDOG_WARNING); 02098 } 02099 02100 $i++; 02101 } 02102 return ''; 02103 } 02104 02105 /** 02106 * 02107 * 02108 * @ingroup tripal_feature 02109 */ 02110 function tripal_feature_return_fasta($feature,$desc){ 02111 $fasta = ">" . variable_get('chado_feature_accession_prefix','ID') . "$feature->feature_id|$feature->name"; 02112 $fasta .= " $desc\n"; 02113 $fasta .= wordwrap($feature->residues, 50, "\n", true); 02114 $fasta .= "\n\n"; 02115 return $fasta; 02116 } 02117 /** 02118 * 02119 * 02120 * @ingroup tripal_feature 02121 */ 02122 function tripal_feature_job_describe_args($callback,$args){ 02123 02124 $new_args = array(); 02125 if($callback == 'tripal_feature_load_fasta'){ 02126 $new_args['FASTA file'] = $args[0]; 02127 $organism = tripal_core_chado_select('organism',array('genus','species'),array('organism_id' => $args[1])); 02128 $new_args['Organism'] = $organism[0]->genus." ". $organism[0]->species; 02129 $new_args['Sequence Type'] = $args[2]; 02130 $new_args['Name RE'] = $args[4]; 02131 $new_args['Unique Name RE'] = $args[5]; 02132 02133 // add in the relationship arguments 02134 $new_args['Relationship Type'] = $args[8]; 02135 $new_args['Relationship Parent RE'] = $args[9]; 02136 $new_args['Relationship Parent Type'] = $args[10]; 02137 02138 // add in the database reference arguments 02139 if($args[7]){ 02140 $db = tripal_core_chado_select('db',array('name'),array('db_id' => $args[7])); 02141 } 02142 $new_args['Database Reference'] = $db[0]->name; 02143 $new_args['Accession RE'] = $args[6]; 02144 if($args[11]){ 02145 $new_args['Update and Insert'] = 'Yes'; 02146 } 02147 else { 02148 $new_args['Insert Only New Features'] = 'Yes'; 02149 } 02150 02151 // add in the analysis 02152 if($args[13]){ 02153 $analysis = tripal_core_chado_select('analysis',array('name'),array('analysis_id' => $args[13])); 02154 } 02155 $new_args['Analysis'] = $analysis[0]->name; 02156 } 02157 return $new_args; 02158 } 02159