Tripal Feature Administrative Tools Quick Links:'; $text .= ""; $text .= '

Module Description:

'; $text .= '

This module provides an interface for the Chado feature module which stores information related to genomic features. This module provides support for bulk loading of data in FASTA or GFF format, visualization of "feature" pages, editing and updating.

'; $text .= '

Setup Instructions:

'; $text .= '

After installation of the feature module. The following tasks should be performed

  1. Set Permissions: The feature module supports the Drupal user permissions interface for controlling access to feature content and functions. These permissions include viewing, creating, editing or administering of feature content. The default is that only the original site administrator has these permissions. You can add roles for classifying users, assign users to roles and assign permissions for the feature content to those roles. For a simple setup, allow anonymous users access to view organism content and allow the site administrator all other permissions.

  2. Themeing: Before content from Chado can be visualized the Tripal base theme must be installed. This should have been done prior to this point. But is mentioned here in the event you follow the instructions below and cannot see content. In this case, if you do not see content check that Tripal theming is properly installed

  3. Loading of Ontologies: If you used Tripal to create the Chado database, then you must load ontologies before proceeding. Visit the page to load ontologies and load at least the following ontologies:

  4. Create Organisms: Before adding feature data you must already have the organisms loaded in the database. See the Tripal Organism Admin page for instructions for adding and Syncing organisms.

  5. Create Analysis: Tripal requires that feature data loaded using the Tripal loaders be associated with an analyis. This provides a grouping for the feature data and can be used later to visualize data pipelines. Before loading feature data through the FASTA or GFF loaders you will need to create an analysis for the data.

  6. Create Database: If you would like to associate your feature data with an external reference database, check to ensure that the database record already exists. If not you should add a new database record before importing feature data.

  7. Data Import: if you do not already have an existing Chado database with preloaded data then you will want to import data. You can do so using the Chado perl scripts that come with the normal distribution of Chado or you can use the FASTA loader and GFF loader provided here. If you created the Chado database using Tripal then you\'ll most likely want to use the Tripal loaders. If your data is not condusive for loading with these loaders you may have to write your own loaders.

  8. Sync Features: After data is loaded you need to sync features. This process is what creates the pages for viewing online. Not all features need be synced. For instance, if you have loaded whole genome sequence with fully defined gene models with several features to define a gene and its products (e.g. gene, mRNA, CDS, 5\'UTR, 3\'UTR, etc) you probably only want to create pages for genes or genes and mRNA. You probably do not want a page for a 5\'UTR. Using the Feature Configuration page you can sync (or create pages) for the desired feature types.

  9. Set Feature URL: It is often convenient to have a simple URL for each feature page. For example, http://www.mygenomesite.org/[feature], where [feature] is a unique identifier for a feature page. With this, people can easily include links to feature pages of interest. Use the Feature Configuration page to specify whether to use the feature name, unique name or internal ID as the [feature] portion of the URL. Select the one that will guarantee a unique identifier for feature pages.

  10. Indexing: Once all data has been loaded (including analysis data--e.g. blast, interpro, etc.) you can index all feature pages for searching if you want to ues the Drupal default search mechanism. Use the Feature Configuration page to either Index (for the first time) or "Reindex" (after adding new data) the feature pages for searching. Once the site is 100% indexed the pages will be searchable using Drupal\'s full text searching. You can find the percent indexed for the entire site by visiting the Search settings page. Indexing can take quite a while if you have a lot of data

  11. Set Taxonomy: Drupal provides a mechanism for categorizing content to allow for advanced searching. Drupal calls this "Taxonomy", but is essentially categorizing the pages. You can categorize feature pages by their type (e.g. gene, mRNA, contig, EST, etc.) and by the organism to which they belong. This allows for filtering of search results by organism and feature type. Use the Feature Configuration page to set the Taxonomy.

'; $text .= '

Features of this Module:

'; $text .= '

Aside from data loading and feature page setup (as described in the Setup section above), The Tripal feature module also provides the following functionality

'; $text .= '

Page Customizations

'; $text .= '

There are several ways to customize the look-and-feel for the way Chado data is presented through Tripal. Below is a description of several methods. These methods may be used in conjunction with one another to provide fine-grained control.

'; return $text; } /** * * * @ingroup tripal_feature */ function tripal_feature_admin () { // before proceeding check to see if we have any // currently processing jobs. If so, we don't want // to give the opportunity to sync libraries $active_jobs = FALSE; if(tripal_get_module_active_jobs('tripal_feature')){ $active_jobs = TRUE; } if(!$active_jobs){ $form['chado_feature_accession_prefix'] = array ( '#title' => t('Internal ID Prefix'), '#type' => t('textfield'), '#description' => t("Internal ID numbers for features consist of the ". "chado feature_id and a site specific prefix. Set the prefix that ". "will be incorporated in front of each feature_id."), '#required' => TRUE, '#default_value' => variable_get('chado_feature_accession_prefix','ID'), ); $form['chado_feature_types'] = array( '#title' => t('Feature Types'), '#type' => 'textarea', '#description' => t('Enter the names of the sequence types that the ". "site will support with independent pages. Pages for these data ". "types will be built automatically for features that exist in the ". "chado database. The names listed here should be spearated by ". "spaces or entered separately on new lines. The names must match ". "exactly (spelling and case) with terms in the sequence ontology'), '#required' => TRUE, '#default_value' => variable_get('chado_feature_types','EST contig'), ); get_tripal_feature_admin_form_sync_set($form); get_tripal_feature_admin_form_url_set($form); $form['browser'] = array( '#type' => 'fieldset', '#title' => t('Feature Browser') ); $allowedoptions1 = array ( 'show_feature_browser' => "Show the feature browser on the organism page. The browser loads when page loads. This may be slow for large sites.", 'hide_feature_browser' => "Hide the feature browser on the organism page. Disables the feature browser completely.", ); // $allowedoptions ['allow_feature_browser'] = "Allow loading of the feature browsing through AJAX. For large sites the initial page load will be quick with the feature browser loading afterwards."; $form['browser']['browse_features'] = array( '#title' => 'Feature Browser on Organism Page', '#description' => 'A feature browser can be added to an organism page to allow users to quickly '. 'access a feature. This will most likely not be the ideal mechanism for accessing feature '. 'information, especially for large sites, but it will alow users exploring the site (such '. 'as students) to better understand the data types available on the site.', '#type' => 'radios', '#options' => $allowedoptions1, '#default_value'=>variable_get('tripal_feature_browse_setting', 'show_feature_browser'), ); $form['browser']['set_browse_button'] = array( '#type' => 'submit', '#value' => t('Set Browser'), '#weight' => 2, ); $form['summary'] = array( '#type' => 'fieldset', '#title' => t('Feature Summary') ); $allowedoptions2 ['show_feature_summary'] = "Show the feature summary on the organism page. The summary loads when page loads."; $allowedoptions2 ['hide_feature_summary'] = "Hide the feature summary on the organism page. Disables the feature summary."; $form['summary']['feature_summary'] = array( '#title' => 'Feature Summary on Organism Page', '#description' => 'A feature summary can be added to an organism page to allow users to see the '. 'type and quantity of features available for the organism.', '#type' => 'radios', '#options' => $allowedoptions2, '#default_value'=>variable_get('tripal_feature_summary_setting', 'show_feature_summary'), ); $form['summary']['set_summary_button'] = array( '#type' => 'submit', '#value' => t('Set Summary'), '#weight' => 2, ); get_tripal_feature_admin_form_taxonomy_set($form); get_tripal_feature_admin_form_reindex_set($form); get_tripal_feature_admin_form_cleanup_set($form); } else { $form['notice'] = array( '#type' => 'fieldset', '#title' => t('Feature Management Temporarily Unavailable') ); $form['notice']['message'] = array( '#value' => t('Currently, feature management jobs are waiting or ". "are running. Managemment features have been hidden until these ". "jobs complete. Please check back later once these jobs have ". "finished. You can view the status of pending jobs in the Tripal ". "jobs page.'), ); } return system_settings_form($form); } /** * * * @ingroup tripal_feature */ function tripal_feature_admin_validate($form, &$form_state) { global $user; // we need access to the user info $job_args = array(); // if the user wants to sync up the chado features then // add the job to the management queue switch ($form_state['values']['op']){ case t('Sync all Features') : tripal_add_job('Sync all features','tripal_feature', 'tripal_feature_sync_features',$job_args,$user->uid); break; case t('Set/Reset Taxonomy for all feature nodes') : tripal_add_job('Set all feature taxonomy','tripal_feature', 'tripal_features_set_taxonomy',$job_args,$user->uid); break; case t('Reindex all feature nodes') : tripal_add_job('Reindex all features','tripal_feature', 'tripal_features_reindex',$job_args,$user->uid); break; case t('Clean up orphaned features') : tripal_add_job('Cleanup orphaned features','tripal_feature', 'tripal_features_cleanup',$job_args,$user->uid); break; case t('Set Browser') : variable_set('tripal_feature_browse_setting',$form_state['values']['browse_features']); break; case t('Set Summary') : variable_set('tripal_feature_summary_setting',$form_state['values']['feature_summary']); break; case t('Set Feature URLs') : variable_set('chado_feature_url',$form_state['values']['feature_url']); tripal_add_job('Set Feature URLs','tripal_feature', 'tripal_feature_set_urls',$job_args,$user->uid); break; } } /** * * * @ingroup tripal_feature */ function get_tripal_feature_admin_form_cleanup_set(&$form) { $form['cleanup'] = array( '#type' => 'fieldset', '#title' => t('Clean Up') ); $form['cleanup']['description'] = array( '#type' => 'item', '#value' => t("With Drupal and chado residing in different databases ". "it is possible that nodes in Drupal and features in Chado become ". "\"orphaned\". This can occur if a feature node in Drupal is ". "deleted but the corresponding chado feature is not and/or vice ". "versa. The Cleanup function will also remove nodes for features ". "that are not in the list of allowed feature types as specified ". "above. This is helpful when a feature type needs to be ". "removed but was previously present as Drupal nodes. ". "Click the button below to resolve these discrepancies."), '#weight' => 1, ); $form['cleanup']['button'] = array( '#type' => 'submit', '#value' => t('Clean up orphaned features'), '#weight' => 2, ); } /** * * * @ingroup tripal_feature */ function get_tripal_feature_admin_form_reindex_set(&$form) { $form['reindex'] = array( '#type' => 'fieldset', '#title' => t('Index/Reindex') ); $form['reindex']['description'] = array( '#type' => 'item', '#value' => t("Indexing or reindexing of nodes is required for Drupal's full text searching. ". "Index features for the first time to allow for searching of content, and later when content for features ". "is updated. Depending on the number of features this may take ". "quite a while. Click the button below to begin reindexing of ". "features. "), '#weight' => 1, ); $form['reindex']['button'] = array( '#type' => 'submit', '#value' => t('Reindex all feature nodes'), '#weight' => 2, ); } /** * * * @ingroup tripal_feature */ function get_tripal_feature_admin_form_taxonomy_set (&$form) { $form['taxonomy'] = array( '#type' => 'fieldset', '#title' => t('Set Taxonomy') ); $form['taxonomy']['description'] = array( '#type' => 'item', '#value' => t("Drupal allows for assignment of \"taxonomy\" or ". "catagorical terms to nodes. These terms allow for advanced ". "filtering during searching."), '#weight' => 1, ); $tax_options = array ( 'organism' => t('Organism name'), 'feature_type' => t('Feature Type (e.g. EST, mRNA, etc.)'), 'analysis' => t('Analysis Name'), 'library' => t('Library Name'), ); $form['taxonomy']['tax_classes'] = array ( '#title' => t('Available Taxonomic Classes'), '#type' => t('checkboxes'), '#description' => t("Please select the class of terms to assign to ". "chado features"), '#required' => FALSE, '#prefix' => '
', '#suffix' => '
', '#options' => $tax_options, '#weight' => 2, '#default_value' => variable_get('tax_classes',''), ); $form['taxonomy']['button'] = array( '#type' => 'submit', '#value' => t('Set/Reset Taxonomy for all feature nodes'), '#weight' => 3, ); } /** * * * @ingroup tripal_feature */ function get_tripal_feature_admin_form_sync_set (&$form) { // get the list of organisms which will be synced. $feature_sql = "SELECT * FROM {Feature} WHERE uniquename = '%s' and organism_id = %d"; $previous_db = tripal_db_set_active('chado'); $feature = db_fetch_object(db_query($feature_sql,$node->title,$node->organism_id)); tripal_db_set_active($previous_db); // define the fieldsets $form['sync'] = array( '#type' => 'fieldset', '#title' => t('Sync Features') ); $form['sync']['description'] = array( '#type' => 'item', '#value' => t("Click the 'Sync all Features' button to create Drupal ". "content for features in chado. Only features of the types listed ". "above in the Feature Types box will be synced. Depending on the ". "number of features in the chado database this may take a long ". "time to complete. "), '#weight' => 1, ); $orgs = tripal_organism_get_synced(); $org_list = ''; foreach($orgs as $org){ $org_list .= "$org->genus $org->species, "; } $form['sync']['description2'] = array( '#type' => 'item', '#value' => "Only features for the following organisms will be synced: ". " $org_list", '#weight' => 1, ); $form['sync']['button'] = array( '#type' => 'submit', '#value' => t('Sync all Features'), '#weight' => 3, ); } function get_tripal_feature_admin_form_url_set (&$form) { $form['url'] = array( '#type' => 'fieldset', '#title' => t('Feature URL Path') ); $form['url']['chado_feature_url'] = array( '#title' => t('Feature URL'), '#type' => 'radios', '#description' => t('Each synced feature will have a unique URL which consists of '. 'the site domain followed by a unique identifer: for '. 'example http://my-tripal-site.org/ID1034, where the '. 'element just after the final slash is the unique '. 'identifier for the feature. Choose a feature descriptor '. 'from the list that is guaranteed to be unique in your synced '. 'dataset. If in doubt it is safest to coose the internal ID. '. 'The descrpitor need not be unique amont the total dataset. '. 'It only need be unique among the synced dataset.'), '#required' => FALSE, '#options' => array('internal ID' => 'internal ID', 'feature unique name' => 'feature unique name', 'feature name' => 'feature name'), '#default_value' => variable_get('chado_feature_url','internal ID'), ); $form['url']['button'] = array( '#type' => 'submit', '#value' => t('Set Feature URLs'), '#weight' => 3, ); } /** * * * @ingroup tripal_feature */ function tripal_feature_aggregator_page(){ $add_url = url("admin/tripal/tripal_feature/aggregate/new"); $output = "Add a new aggregator"; $output .= drupal_get_form('tripal_feature_aggregator_select_form'); $output .= '
Please select an aggregator base type to view or edit
'; return $output; } /** * * * @ingroup tripal_feature */ function tripal_feature_aggregator_select_form(){ // get a list of base terms from chado for user to choose $sql = "SELECT DISTINCT type_id FROM {tripal_feature_relagg} ORDER BY type_id "; $results = db_query ($sql); $sql = "SELECT * FROM {cvterm} WHERE cvterm_id = %d"; $previous_db = tripal_db_set_active('chado'); $types = array(); $types[] = ''; while($base = db_fetch_object($results)){ $term = db_fetch_object(db_query($sql,$base->type_id)); $types[$base->type_id] = $term->name; } tripal_db_set_active($previous_db); $form['type_id'] = array( '#title' => t('Aggregator Base Type'), '#type' => 'select', '#options' => $types, '#ahah' => array( 'path' => 'admin/tripal/tripal_feature/aggregate/edit/js', 'wrapper' => 'db-edit-div', 'effect' => 'fade', 'event' => 'change', 'method' => 'replace', ), ); return $form; } /** * * * @ingroup tripal_feature */ function tripal_feature_aggregator_form(&$form_state = NULL,$type_id = NULL){ // get this requested database if($type_id){ $sql = "SELECT * FROM {tripal_feature_relagg} WHERE type_id = %d "; $tsql = "SELECT * FROM {cvterm} WHERE cvterm_id = %d "; // get the default list of terms $results = db_query($sql,$type_id); while($type = db_fetch_object($results)){ $previous_db = tripal_db_set_active('chado'); $term = db_fetch_object(db_query($tsql,$type->rel_type_id)); tripal_db_set_active($previous_db); $default_others .= $term->name . " "; } $default_base = $base->name; $action = 'Update'; $form['type_id'] = array( '#type' => 'hidden', '#value' => $type_id ); } else { $action = 'Add'; $form['base']= array( '#type' => 'textfield', '#title' => t('Base Feature type'), '#description' => t('Please enter the Sequence Ontology (SO) term for the base feature type for this aggregator.'), '#default_value' => $default_base, '#required' => TRUE, '#weight' => 1 ); } $form['others']= array( '#type' => 'textarea', '#title' => t('Aggregate these types if a relationship exists'), '#description' => t('Please enter the Sequence Ontology (SO) terms that should be aggregated with the base feature type listed above. Separate each by a space or newline'), '#default_value' => $default_others, '#required' => TRUE, '#weight' => 2 ); if(strcmp($action,'Update')==0){ $form['update'] = array ( '#type' => 'submit', '#value' => t('Update'), '#weight' => 5, '#executes_submit_callback' => TRUE, ); $form['delete'] = array ( '#type' => 'submit', '#value' => t('Delete'), '#weight' => 6, '#executes_submit_callback' => TRUE, ); } else { $form['add'] = array ( '#type' => 'submit', '#value' => t('Add'), '#weight' => 5, '#executes_submit_callback' => TRUE, ); } $form['#redirect'] = 'admin/tripal/tripal_feature/aggregate'; return $form; } /** * * * @ingroup tripal_feature */ function tripal_feature_aggregator_form_validate($form, &$form_state){ $type_id = $form_state['values']['type_id']; $base = $form_state['values']['base']; $others = $form_state['values']['others']; $op = $form_state['values']['op']; // split apart the feature types to be aggregated $types = preg_split('/\s+/',$others); // the SQL for finding the term $tsql = " SELECT * FROM {cvterm} CVT INNER JOIN {cv} CV on CVT.cv_id = CV.cv_id WHERE CVT.name = '%s' and CV.name = 'sequence'"; // make sure the base type exists if($base){ $previous_db = tripal_db_set_active('chado'); $term = db_fetch_object(db_query($tsql,$base)); tripal_db_set_active($previous_db); if(!$term){ form_set_error('base',t('The specified base type is not a valid SO term')); } // make sure this type doesn't already in the table $sql = "SELECT * FROM {tripal_feature_relagg} WHERE type_id = %d "; $agg = db_fetch_object(db_query($sql,$term->cvterm_id)); if($agg){ form_set_error('base',t('The specified base type is already used as a base type for another aggregator and cannot be readded.')); } } // iterate through each type to be aggregated and make sure they are valid foreach($types as $type){ $previous_db = tripal_db_set_active('chado'); $term = db_fetch_object(db_query($tsql,$type)); tripal_db_set_active($previous_db); if(!$term){ form_set_error('others',t('The specified type ') . $type . t(' is not a valid SO term')); } } } /** * * * @ingroup tripal_feature */ function tripal_feature_aggregator_form_submit($form, &$form_state){ $type_id = $form_state['values']['type_id']; $base = $form_state['values']['base']; $others = $form_state['values']['others']; $op = $form_state['values']['op']; // split apart the feature types to be aggregated $types = preg_split('/\s+/',$others); // the SQL for finding the term $tsql = " SELECT * FROM {cvterm} CVT INNER JOIN {cv} CV on CVT.cv_id = CV.cv_id WHERE CVT.name = '%s' and CV.name = 'sequence'"; // the SQL for deleting an aggregator $dsql = " DELETE FROM {tripal_feature_relagg} WHERE type_id = %d "; // if this is an insert then we have a base type name. We // need to get the corresponding term id if($base){ $previous_db = tripal_db_set_active('chado'); $term = db_fetch_object(db_query($tsql,$base)); tripal_db_set_active($previous_db); $type_id = $term->cvterm_id; } if(strcmp($op,'Delete')==0){ $result = db_query($dsql,$type_id); if($result){ drupal_set_message("Aggregator deleted"); } else { drupal_set_message("Failed to delete mailing list."); } } else { // for an update, first remove all the current aggregator settings // and we'll add them again $result = db_query($dsql,$type_id); // the SQL for inserting the aggregated types $isql = " INSERT INTO {tripal_feature_relagg} (type_id,rel_type_id) VALUES (%d,%d) "; // iterate through each type to be aggregated and add an entry in the table foreach($types as $type){ $previous_db = tripal_db_set_active('chado'); $term = db_fetch_object(db_query($tsql,$type)); tripal_db_set_active($previous_db); $result = db_query($isql,$type_id,$term->cvterm_id); } drupal_set_message("Aggregator added"); } return ''; } /** * * * @ingroup tripal_feature */ function tripal_feature_aggregator_ajax_edit (){ // get the database id, build the form and then return the JSON object $type_id = $_POST['type_id']; $form = drupal_get_form('tripal_feature_aggregator_form',$type_id); drupal_json(array('status' => TRUE, 'data' => $form)); }