2.0, ); } /************************************************************************ * Display help and module information * @param path which path of the site we're displaying help * @param arg array that holds the current path as would be returned from arg() function * @return help text for the path */ function tripal_feature_help($path, $arg) { $output = ''; switch ($path) { case "admin/help#tripal_feature": $output='
'.t("Displays links to nodes created on this date").'
'; break; } return $output; } /************************************************************************ * Provide information to drupal about the node types that we're creating * in this module */ function tripal_feature_node_info() { $nodes = array(); $nodes['chado_feature'] = array( 'name' => t('Feature'), 'module' => 'chado_feature', 'description' => t('A feature from the chado database'), 'has_title' => FALSE, 'title_label' => t('Feature'), 'has_body' => FALSE, 'body_label' => t('Feature Description'), 'locked' => TRUE ); return $nodes; } /************************************************************************ * Set the permission types that the chado module uses. Essentially we * want permissionis that protect creation, editing and deleting of chado * data objects */ function tripal_feature_perm(){ return array( 'access chado_feature content', 'create chado_feature content', 'delete chado_feature content', 'edit chado_feature content', ); } /************************************************************************ * Set the permission types that the module uses. */ function chado_feature_access($op, $node, $account) { if ($op == 'create') { return user_access('create chado_feature content', $account); } if ($op == 'update') { if (user_access('edit chado_feature content', $account)) { return TRUE; } } if ($op == 'delete') { if (user_access('delete chado_feature content', $account)) { return TRUE; } } if ($op == 'view') { if (user_access('access chado_feature content', $account)) { return TRUE; } } return FALSE; } /************************************************************************ * Menu items are automatically added for the new node types created * by this module to the 'Create Content' Navigation menu item. This function * adds more menu items needed for this module. */ function tripal_feature_menu() { $items = array(); // the administative settings menu $items['admin/tripal/tripal_feature'] = array( 'title' => 'Features', 'description' => 'Settings for Chado Features', 'page callback' => 'drupal_get_form', 'page arguments' => array('tripal_feature_admin'), 'access arguments' => array('administer site configuration'), 'type' => MENU_NORMAL_ITEM, ); $items['admin/tripal/fasta_loader'] = array( 'title' => 'Import a multi-FASTA file', 'description' => 'Load sequences from a multi-FASTA file into Chado', 'page callback' => 'drupal_get_form', 'page arguments' => array('tripal_feature_fasta_load_form'), 'access arguments' => array('administer site configuration'), 'type' => MENU_NORMAL_ITEM, ); // Adding Secondary Properties----------------- $items['node/%tripal_feature_node/properties'] = array( 'title' => t('Add Properties & Synonyms'), 'description' => t('Settings for Features'), 'page callback' => 'tripal_feature_add_ALL_property_page', 'page arguments' => array(1), 'access arguments' => array('create chado_feature content'), 'type' => MENU_CALLBACK ); $items['node/%tripal_feature_node/db_references'] = array( 'title' => t('Add Database References'), 'description' => t('Settings for Features'), 'page callback' => 'tripal_feature_add_ALL_dbreferences_page', 'page arguments' => array(1), 'access arguments' => array('create chado_feature content'), 'type' => MENU_CALLBACK ); $items['node/%tripal_feature_node/relationships'] = array( 'title' => t('Add Relationships'), 'description' => t('Settings for Features'), 'page callback' => 'tripal_feature_add_ALL_relationships_page', 'page arguments' => array(1), 'access arguments' => array('create chado_feature content'), 'type' => MENU_CALLBACK ); //Edit/Deleting Secondary Properties------------- $items['node/%tripal_feature_node/edit_properties'] = array( 'title' => t('Edit Properties'), 'description' => t('Settings for Features'), 'page callback' => 'tripal_feature_edit_ALL_properties_page', 'page arguments' => array(1), 'access arguments' => array('edit chado_feature content'), 'type' => MENU_LOCAL_TASK, 'weight' => 8, ); $items['node/%tripal_feature_node/edit_relationships'] = array( 'title' => t('Edit Relationships'), 'description' => t('Settings for Feature'), 'page callback' => 'tripal_feature_edit_ALL_relationships_page', 'page arguments' => array(1), 'access arguments' => array('edit chado_feature content'), 'type' => MENU_LOCAL_TASK, 'weight' => 9, ); $items['node/%tripal_feature_node/edit_db_references'] = array( 'title' => t('Edit References'), 'description' => t('Settings for Feature'), 'page callback' => 'tripal_feature_edit_ALL_dbreferences_page', 'page arguments' => array(1), 'access arguments' => array('edit chado_feature content'), 'type' => MENU_LOCAL_TASK, 'weight' => 10, ); return $items; } /************************************************************************* * Implements Menu wildcard_load hook * Purpose: Allows the node ID of a chado stock to be dynamically * pulled from the path. The node is loaded from this node ID * and supplied to the page as an arguement */ function tripal_feature_node_load($nid) { if (is_numeric($nid)) { $node = node_load($nid); if ($node->type == 'chado_feature') { return $node; } } return FALSE; } /************************************************************************ * When a new chado_feature node is created we also need to add information * to our chado_feature table. This function is called on insert of a new node * of type 'chado_feature' and inserts the necessary information. */ function chado_feature_insert($node){ // remove spaces, newlines from residues $residues = preg_replace("/[\n\r\s]/","",$node->residues); // If this feature already exists then don't recreate it in chado // TODO: the unique index in chado for this also includes the type_id. If the site // ever needs to have the same feature name for different types then this will break. $feature_sql = "SELECT * FROM {Feature} F INNER JOIN {cvterm} CVT ON F.type_id = CVT.cvterm_id WHERE uniquename = '%s' and organism_id = %d and CVT.name = '%s'"; $previous_db = tripal_db_set_active('chado'); $feature = db_fetch_object(db_query($feature_sql,$node->uniquename,$node->organism_id,$node->feature_type)); tripal_db_set_active($previous_db); // if the feature doesn't exist then let's create it in chado. if(!$feature){ $sql = "INSERT INTO {feature} (organism_id, name, uniquename, residues, seqlen,". " is_obsolete, type_id)". " VALUES(%d,'%s','%s','%s',%d, %s, ". " (SELECT cvterm_id ". " FROM {CVTerm} CVT ". " INNER JOIN CV ON CVT.cv_id = CV.cv_id ". " WHERE CV.name = 'sequence' and CVT.name = '%s'))"; $obsolete = 'FALSE'; if($node->is_obsolete){ $obsolete = 'TRUE'; } // use chado database $previous_db = tripal_db_set_active('chado'); db_query($sql,$node->organism_id,$node->name,$node->uniquename, $residues,strlen($residues),$obsolete,$node->feature_type); // now that we've added the feature, get the feature id for this feature $feature = db_fetch_object(db_query($feature_sql,$node->uniquename,$node->organism_id,$node->feature_type)); // now use drupal database tripal_db_set_active($previous_db); } // add the genbank accession and synonyms chado_feature_add_synonyms($node->synonyms,$feature->feature_id); // make sure the entry for this feature doesn't already exist in the chado_feature table // if it doesn't exist then we want to add it. $node_check_sql = "SELECT * FROM {chado_feature} ". "WHERE feature_id = '%s'"; $node_check = db_fetch_object(db_query($node_check_sql,$feature->feature_id)); if(!$node_check){ // next add the item to the drupal table $sql = "INSERT INTO {chado_feature} (nid, vid, feature_id, sync_date) ". "VALUES (%d, %d, %d, " . time() . ")"; db_query($sql,$node->nid,$node->vid,$feature->feature_id); } } /************************************************************************ */ function chado_feature_delete($node){ // get feature_id so we can remove it from chado database $sql_drupal = "SELECT feature_id ". "FROM {chado_feature} ". "WHERE nid = %d AND vid = %d"; $feature_id = db_result(db_query($sql_drupal, $node->nid, $node->vid)); // remove the drupal content $sql_del = "DELETE FROM {chado_feature} ". "WHERE nid = %d ". "AND vid = %d"; db_query($sql_del, $node->nid, $node->vid); $sql_del = "DELETE FROM {node} ". "WHERE nid = %d ". "AND vid = %d"; db_query($sql_del, $node->nid, $node->vid); $sql_del = "DELETE FROM {node_revisions} ". "WHERE nid = %d ". "AND vid = %d"; db_query($sql_del, $node->nid, $node->vid); // Remove data from feature tables of chado database. This will // cause a cascade delete and remove all data in referencing tables // for this feature $previous_db = tripal_db_set_active('chado'); db_query("DELETE FROM {feature} WHERE feature_id = %d", $feature_id); tripal_db_set_active($previous_db); drupal_set_message("The feature and all associated data were removed from ". "chado"); } /************************************************************************ */ function chado_feature_update($node){ if($node->revision){ // TODO -- decide what to do about revisions } else { // get the feature for this node: $sql = 'SELECT feature_id FROM {chado_feature} WHERE vid = %d'; $feature = db_fetch_object(db_query($sql, $node->vid)); // remove spaces, newlines from residues $residues = preg_replace("/[\n\r\s]/","",$node->residues); $sql = "UPDATE {feature} ". " SET residues = '%s', ". " name = '%s', ". " uniquename = '%s', ". " seqlen = %d, ". " organism_id = %d, ". " is_obsolete = %s, ". " type_id = (SELECT cvterm_id ". " FROM {CVTerm} CVT ". " INNER JOIN CV ON CVT.cv_id = CV.cv_id ". " WHERE CV.name = 'sequence' and CVT.name = '%s') ". "WHERE feature_id = %d "; $obsolete = 'FALSE'; if($node->is_obsolete){ $obsolete = 'TRUE'; } $previous_db = tripal_db_set_active('chado'); // use chado database db_query($sql,$residues,$node->name,$node->uniquename, strlen($residues),$node->organism_id,$obsolete,$node->feature_type, $feature->feature_id); tripal_db_set_active($previous_db); // now use drupal database // add the genbank accession & synonyms // chado_feature_add_gbaccession($node->gbaccession,$feature->feature_id); chado_feature_add_synonyms($node->synonyms,$feature->feature_id); } } /************************************************************************ * */ function chado_feature_add_synonyms($synonyms,$feature_id){ // make sure we only have a single space between each synonym $synonyms = preg_replace("/[\s\n\r]+/"," ",$synonyms); // split the synonyms into an array based on a space as the delimieter $syn_array = array(); $syn_array = explode(" ",$synonyms); // use the chado database $previous_db = tripal_db_set_active('chado'); // remove any old synonyms $feature_syn_dsql = "DELETE FROM {feature_synonym} WHERE feature_id = %d"; if(!db_query($feature_syn_dsql,$feature_id)){ $error .= "Could not remove synonyms from feature. "; } // return if we don't have any synonmys to add if(!$synonyms){ tripal_db_set_active($previous_db); return; } // iterate through each synonym and add it to the database foreach($syn_array as $syn){ // skip this item if it's empty if(!$syn){ break; } // check to see if we have this accession number already in the database // if so then don't add it again. it messes up drupal if the insert fails. // It is possible for the accession number to be present and not the feature $synonym_sql = "SELECT synonym_id FROM {synonym} ". "WHERE name = '%s'"; $synonym = db_fetch_object(db_query($synonym_sql,$syn)); if(!$synonym){ $synonym_isql = "INSERT INTO {synonym} (name,synonym_sgml,type_id) ". "VALUES ('%s','%s', ". " (SELECT cvterm_id ". " FROM {CVTerm} CVT ". " INNER JOIN CV ON CVT.cv_id = CV.cv_id ". " WHERE CV.name = 'feature_property' and CVT.name = 'synonym'))"; if(!db_query($synonym_isql,$syn,$syn)){ $error .= "Could not add synonym. "; } // now get the synonym we just added $synonym_sql = "SELECT synonym_id FROM {synonym} ". "WHERE name = '%s'"; $synonym = db_fetch_object(db_query($synonym_sql,$syn)); } // now add in our new sysnonym $feature_syn_isql = "INSERT INTO {feature_synonym} (synonym_id,feature_id,pub_id) ". "VALUES (%d,%d,1)"; if(!db_query($feature_syn_isql,$synonym->synonym_id,$feature_id)){ $error .= "Could not add synonyms to feature. "; } } // return to the drupal database tripal_db_set_active($previous_db); return $error; } /************************************************************************ * */ function chado_feature_add_gbaccession($accession,$feature_id){ // use chado database $previous_db = tripal_db_set_active('chado'); // remove any old accession from genbank dbEST $fdbxref_dsql = "DELETE FROM {feature_dbxref} ". "WHERE feature_id = %d and dbxref_id IN ". " (SELECT DBX.dbxref_id FROM {dbxref} DBX ". " INNER JOIN DB ON DB.db_id = DBX.db_id ". " INNER JOIN feature_dbxref FDBX ON DBX.dbxref_id = FDBX.dbxref_id ". " WHERE DB.name = 'DB:Genbank' and FDBX.feature_id = %d)"; if(!db_query($fdbxref_dsql,$feature_id,$feature_id)){ $error .= "Could not remove accession from feature. "; } // if we don't have an accession number to add then just return if(!$accession){ tripal_db_set_active($previous_db); return; } // get the db_id $db_sql = "SELECT db_id FROM {DB} ". "WHERE name = 'DB:Genbank_est'"; $db = db_fetch_object(db_query($db_sql)); // check to see if we have this accession number already in the database // if so then don't add it again. it messes up drupal if the insert fails. // It is possible for the accession number to be present and not the feature $dbxref_sql = "SELECT dbxref_id FROM {dbxref} ". "WHERE db_id = %d and accession = '%s'"; $dbxref = db_fetch_object(db_query($dbxref_sql,$db->db_id,$accession)); if(!$dbxref){ // add the accession number $dbxref_isql = "INSERT INTO {dbxref} (db_id,accession) ". " VALUES (%d, '%s') "; if(!db_query($dbxref_isql,$db->db_id,$accession)){ $error .= 'Could not add accession as a database reference '; } // get the dbxref_id for the just added accession number $dbxref_sql = "SELECT dbxref_id FROM {dbxref} ". "WHERE db_id = %d and accession = '%s'"; $dbxref = db_fetch_object(db_query($dbxref_sql,$db->db_id,$accession)); } // associate the accession number with the feature $feature_dbxref_isql = "INSERT INTO {feature_dbxref} (feature_id,dbxref_id) ". " VALUES (%d, %d) "; if(!db_query($feature_dbxref_isql,$feature_id,$dbxref->dbxref_id)){ $error .= 'Could not add feature database reference. '; } tripal_db_set_active($previous_db); return $error; } /************************************************************************ * */ function chado_feature_form ($node,$param){ $type = node_get_types('type', $node); $form = array(); $feature = $node->feature; $synonyms = $node->synonyms; $analyses = $node->analyses; $references = $node->references; // We need to pass above variables for preview to show $form['feature'] = array( '#type' => 'value', '#value' => $feature ); // This field is read when previewing a node $form['synonyms'] = array( '#type' => 'value', '#value' => $synonyms ); // This field is read when previewing a node $form['analyses'] = array( '#type' => 'value', '#value' => $analyses ); // This field is read when previewing a node $form['references'] = array( '#type' => 'value', '#value' => $references ); // keep track of the feature id if we have one. If we do have one then // this would indicate an update as opposed to an insert. $form['feature_id'] = array( '#type' => 'value', '#value' => $feature->feature_id, ); $form['title']= array( '#type' => 'textfield', '#title' => t('Title'), '#required' => TRUE, '#default_value' => $feature->featurename, '#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.'), '#weight' => 1, '#maxlength' => 255 ); $form['uniquename']= array( '#type' => 'textfield', '#title' => t('Unique Feature Name'), '#required' => TRUE, '#default_value' => $feature->featurename, '#description' => t('Enter a unique name for this feature. This name must be unique for the organism and feature type.'), '#weight' => 1, '#maxlength' => 255 ); $form['name']= array( '#type' => 'textfield', '#title' => t('Feature Name'), '#required' => TRUE, '#default_value' => $feature->featurename, '#description' => t('Enter the name used by humans to refer to this feature.'), '#weight' => 1, '#maxlength' => 255 ); // get the list of supported feature types $ftypes = array(); $ftypes[''] = ''; $supported_ftypes = split("[ \n]",variable_get('chado_feature_types','EST contig')); foreach($supported_ftypes as $ftype){ $ftypes["$ftype"] = $ftype; } $form['feature_type'] = array ( '#title' => t('Feature Type'), '#type' => t('select'), '#description' => t("Choose the feature type."), '#required' => TRUE, '#default_value' => $feature->cvname, '#options' => $ftypes, '#weight' => 2 ); // get the list of organisms $sql = "SELECT * FROM {Organism} ORDER BY genus, species"; $previous_db = tripal_db_set_active('chado'); // use chado database $org_rset = db_query($sql); tripal_db_set_active($previous_db); // now use drupal database // $organisms = array(); $organisms[''] = ''; while($organism = db_fetch_object($org_rset)){ $organisms[$organism->organism_id] = "$organism->genus $organism->species ($organism->common_name)"; } $form['organism_id'] = array ( '#title' => t('Organism'), '#type' => t('select'), '#description' => t("Choose the organism with which this feature is associated "), '#required' => TRUE, '#default_value' => $feature->organism_id, '#options' => $organisms, '#weight' => 3, ); // Get synonyms if ($synonyms) { if (is_array($synonyms)) { foreach ($synonyms as $synonym){ $syn_text .= "$synonym->name\n"; } } else { $syn_text = $synonyms; } } $form['synonyms']= array( '#type' => 'textarea', '#title' => t('Synonyms'), '#required' => FALSE, '#default_value' => $syn_text, '#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.'), '#weight' => 5, ); $form['residues']= array( '#type' => 'textarea', '#title' => t('Residues'), '#required' => FALSE, '#default_value' => $feature->residues, '#description' => t('Enter the nucelotide sequences for this feature'), '#weight' => 6 ); $checked = ''; if($feature->is_obsolete == 't'){ $checked = '1'; } $form['is_obsolete']= array( '#type' => 'checkbox', '#title' => t('Is Obsolete'), '#required' => FALSE, '#default_value' => $checked, '#description' => t('Check this box if this sequence should be retired and no longer included in further analysis.'), '#weight' => 8 ); return $form; } /************************************************************************ * */ function chado_feature_validate($node){ $result = 0; // if this is an update, we want to make sure that a different feature for // the organism doesn't already have this uniquename. We don't want to give // two sequences the same uniquename if($node->feature_id){ $sql = "SELECT * FROM {Feature} F INNER JOIN {cvterm} CVT ON F.type_id = CVT.cvterm_id WHERE uniquename = '%s' AND organism_id = %d AND CVT.name = '%s' AND NOT feature_id = %d"; $previous_db = tripal_db_set_active('chado'); $result = db_fetch_object(db_query($sql, $node->uniquename,$node->organism_id,$node->feature_type,$node->feature_id)); tripal_db_set_active($previous_db); if($result){ 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. ")); } } // if this is an insert then we just need to make sure this name doesn't // already exist for this organism if it does then we need to throw an error else { $sql = "SELECT * FROM {Feature} F INNER JOIN {cvterm} CVT ON F.type_id = CVT.cvterm_id WHERE uniquename = '%s' AND organism_id = %d AND CVT.name = '%s'"; $previous_db = tripal_db_set_active('chado'); $result = db_fetch_object(db_query($sql, $node->uniquename,$node->organism_id,$node->feature_type)); tripal_db_set_active($previous_db); if($result){ 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. ")); } } // we want to remove all characters except IUPAC nucleotide characters from the // the residues. however, residues are not required so if blank then we'll skip // this step if($node->residues){ $residues = preg_replace("/[^\w]/",'',$node->residues); if(!preg_match("/^[ACTGURYMKSWBDHVN]+$/i",$residues)){ 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 ."'")); } } // we don't allow a genbank accession number for a contig if($node->feature_type == 'contig' and $node->gbaccession){ form_set_error('gbaccession',t("Contigs cannot have a genbank accession number. Please change the feature type or remove the accession number")); } } /************************************************************************ * When a node is requested by the user this function is called to allow us * to add auxiliary data to the node object. */ function chado_feature_load($node){ // add the feature_id for this node: $sql = 'SELECT feature_id FROM {chado_feature} WHERE vid = %d'; $map = db_fetch_object(db_query($sql, $node->vid)); // get information about this feature and add it to the items in this node $sql = "SELECT F.feature_id, F.name as featurename, F.uniquename, ". "F.residues, F.seqlen, O.genus, O.species, O.common_name, ". " CVT.name as cvname, O.organism_id, F.type_id, F.is_obsolete ". "FROM {Feature} F ". " INNER JOIN Organism O ON F.organism_id = O.organism_id ". " INNER JOIN CVterm CVT ON F.type_id = CVT.cvterm_id ". "WHERE F.feature_id = %d"; $previous_db = tripal_db_set_active('chado'); // use chado database $feature = db_fetch_object(db_query($sql,$map->feature_id)); tripal_db_set_active($previous_db); // now use drupal database $additions->feature = $feature; $additions->seqlen = $feature->seqlen; // add organism node nid $sql = "SELECT nid FROM {chado_organism} WHERE organism_id = %d"; $org_nid = db_result(db_query($sql, $additions->feature->organism_id)); $additions->org_nid = $org_nid; $additions->accession = variable_get('chado_feature_accession_prefix','ID') . $feature->feature_id; // add organism details $sql = "SELECT * FROM {organism} WHERE organism_id = %d"; $previous_db = tripal_db_set_active('chado'); // use chado database $organism = db_fetch_object(db_query($sql, $additions->feature->organism_id)); tripal_db_set_active($previous_db); // now use drupal database $additions->organism = $organism; // add the feature synonyms $sql = "SELECT S.name ". "FROM {Feature_Synonym} FS ". " INNER JOIN Synonym S ". " ON FS.synonym_id = S.Synonym_id ". "WHERE FS.feature_id = %d"; $previous_db = tripal_db_set_active('chado'); // use chado database $results = db_query($sql,$map->feature_id); tripal_db_set_active($previous_db); // now use drupal database $synonyms = array(); $i=0; while($synonym = db_fetch_object($results)){ $synonyms[$i++] = $synonym; } $additions->synonyms = $synonyms; // add feature references in external databases $sql = "SELECT F.uniquename,F.Feature_id,DBX.accession,DB.description as dbdesc, ". " DB.db_id, DB.name as db_name, DB.urlprefix,DBX.dbxref_id ". "FROM {Feature} F ". " INNER JOIN Feature_dbxref FDBX on F.feature_id = FDBX.feature_id ". " INNER JOIN Dbxref DBX on DBX.dbxref_id = FDBX.dbxref_id ". " INNER JOIN DB on DB.db_id = DBX.db_id ". "WHERE F.feature_id = %d"; $previous_db = tripal_db_set_active('chado'); // use chado database $results = db_query($sql,$map->feature_id); tripal_db_set_active($previous_db); // now use drupal database $references = array(); $i=0; while($accession = db_fetch_object($results)){ $references[$i++] = $accession; } $additions->references = $references; // add the feature relationsips $sql = "SELECT FS.name as subject_name, FS.uniquename as subject_uniquename, FS.residues as subject_residues, CVTS.name as subject_type, FR.subject_id, FR.type_id as relationship_type_id, CVT.name as rel_type, FO.name as object_name, FO.uniquename as object_uniquename, CVTO.name as object_type, FR.object_id, FLS.name as src_name, FLS.uniquename as src_uniquename, FLS.feature_id as src_featureid, CVTR.name as src_cvname, CVTR.cvterm_id as src_type_id, FL.fmin, FL.fmax, FL.is_fmin_partial, FL.is_fmax_partial, FL.strand, FL.phase, FL.residue_info FROM {feature_relationship} FR INNER JOIN {cvterm} CVT ON FR.type_id = CVT.cvterm_id INNER JOIN {feature} FS ON FS.feature_id = FR.subject_id INNER JOIN {feature} FO ON FO.feature_id = FR.object_id INNER JOIN {cvterm} CVTO ON FO.type_id = CVTO.cvterm_id INNER JOIN {cvterm} CVTS ON FS.type_id = CVTS.cvterm_id LEFT JOIN {featureloc} FL on FL.feature_id = FS.feature_id LEFT JOIN {feature} FLS on FLS.feature_id = FL.srcfeature_id LEFT JOIN {cvterm} CVTR on FLS.type_id = CVTR.cvterm_id "; $osql = "$sql WHERE FR.object_id = %d ORDER BY FLS.name, FL.fmin ASC"; $ssql = "$sql WHERE FR.subject_id = %d ORDER BY FLS.name, FL.fmin ASC"; // first get the relationships where this feature is the object // then where it is the subject $previous_db = tripal_db_set_active('chado'); // use chado database $oresults = db_query($osql, $map->feature_id); $sresults = db_query($ssql, $map->feature_id); tripal_db_set_active($previous_db); // now use drupal database // identify the drupal node for each feature and add that to the // relationship records $srelationships = array(); $orelationships = array(); $i=0; $nodesql = "SELECT nid FROM {chado_feature} WHERE feature_id = %d"; $rel_locs; // holds relationship locations $rel_loc; // a single relationship location while($rel = db_fetch_object($oresults)){ $node = db_fetch_object(db_query($nodesql,$rel->subject_id)); if($node){ $rel->subject_nid = $node->nid; } $node = db_fetch_object(db_query($nodesql,$rel->object_id)); if($node){ $rel->object_nid = $node->nid; } $orelationships[$i] = $rel; if($rel->src_uniquename){ $rel_loc = $rel->src_uniquename ."|".$rel->src_type_id; $rel_locs[$rel_loc]['uname'] = $rel->src_uniquename; $rel_locs[$rel_loc]['type'] = $rel->src_type_id; if(!$rel_locs[$rel_loc]['source_min']){ $rel_locs[$rel_loc]['source_min'] = 99999999999; } if($rel->fmin < $rel_locs[$rel_loc]['source_min']){ $rel_locs[$rel_loc]['source_min'] = $rel->fmin; } if($rel->fmax > $rel_locs[$rel_loc]['source_max']){ $rel_locs[$rel_loc]['source_max'] = $rel->fmax; } } $i++; } // build the parts array needed for coloring the relationsihps in the // reference sequence foreach($orelationships as $index => $rel){ if($rel->src_uniquename){ $rel_loc = $rel->src_uniquename ."|".$rel->src_type_id; $rel_locs[$rel_loc]['parts'][$index]['type'] = $rel->subject_type; $rel_locs[$rel_loc]['parts'][$index]['start'] = $rel->fmin - $rel_locs[$rel_loc]['source_min']; $rel_locs[$rel_loc]['parts'][$index]['end'] = $rel->fmax - $rel_locs[$rel_loc]['source_min']; } } $i=0; while($rel = db_fetch_object($sresults)){ $node = db_fetch_object(db_query($nodesql,$rel->subject_id)); if($node){ $rel->subject_nid = $node->nid; } $node = db_fetch_object(db_query($nodesql,$rel->object_id)); if($node){ $rel->object_nid = $node->nid; } $srelationships[$i++] = $rel; } $additions->object_relationships = $orelationships; $additions->subject_relationships = $srelationships; // now get the sequence from the reference for those feature as a // subject relationship to this feature. $object_context = array(); $i=0; foreach ($rel_locs as $rel_loc => $attrs){ if($attrs['uname']){ $sql = "SELECT residues FROM feature WHERE uniquename = '%s' AND organism_id = %d and type_id = %d"; $context = db_fetch_object(db_query($sql,$attrs['uname'],$additions->feature->organism_id,$attrs['type'])); $context->residues = substr($context->residues,$attrs['source_min'],$attrs['source_max'] - $attrs['source_min']); $context->source = $attrs['uname']; $context->fmin = $attrs['source_min']; $context->fmax = $attrs['source_max']; $context->residues = tripal_feature_color_sequence ($context->residues,$attrs['parts']); } $object_context[$i] = $context; } $additions->relationship_object_info = $object_context; // get the locations for this feature $sql = "SELECT F.name,F.feature_id, F.uniquename,CVT.name as cvname, CVT.cvterm_id, FL.fmin, FL.fmax, FL.is_fmin_partial, FL.is_fmax_partial,FL.strand, FL.phase, FL.residue_info FROM featureloc FL INNER JOIN feature F on FL.srcfeature_id = F.feature_id INNER JOIN cvterm CVT on F.type_id = CVT.cvterm_id WHERE FL.feature_id = %d"; $previous_db = tripal_db_set_active('chado'); // use chado database $flresults = db_query($sql, $map->feature_id); tripal_db_set_active($previous_db); // now use drupal database $i=0; $featurelocs = array(); while($loc = db_fetch_object($flresults)){ $featurelocs[$i++] = $loc; } $additions->featurelocs = $featurelocs; // get features that are aligned to this feature $sql = "SELECT F.name,F.feature_id, F.uniquename,CVT.name as cvname, CVT.cvterm_id, FL.fmin, FL.fmax, FL.is_fmin_partial, FL.is_fmax_partial,FL.strand, FL.phase, FL.residue_info FROM featureloc FL INNER JOIN feature F on FL.feature_id = F.feature_id INNER JOIN cvterm CVT on F.type_id = CVT.cvterm_id WHERE FL.srcfeature_id = %d"; $previous_db = tripal_db_set_active('chado'); // use chado database $flresults = db_query($sql, $map->feature_id); tripal_db_set_active($previous_db); // now use drupal database $i=0; $myfeaturelocs = array(); while($loc = db_fetch_object($flresults)){ $myfeaturelocs[$i++] = $loc; } $additions->myfeaturelocs = $myfeaturelocs; return $additions; } /************************************************************************ * */ function tripal_feature_color_sequence ($sequence,$parts){ watchdog('tripal_feature',print_r($parts,1)); $types = array(); // first get the list of types so we can create a color legend foreach ($parts as $index => $child){ $type = $child['type']; if(!in_array($type,$types)){ $types[] = $type; } } $newseq .= "";
foreach ($parts as $index => $child){
$type = $child['type'];
$start = $child['start'];
$end = $child['end'];
$class = "class=\"tripal_feature-sequence-$type\"";
// iterate through the sequence up to the end of the child
for ($i = $pos; $i < $end; $i++){
// if we're at the beginning of the child sequence then set the
// appropriate text color
if($pos == $start){
$newseq .= "";
$func = 'uc'; // nucleotides within the child should be uppercase
}
$newseq .= $sequence{$pos};
$seqcount++;
if($seqcount % 100 == 0){
$newseq .= "\n";
}
$pos++;
if($pos == $end){
$newseq .= "";
$func = 'lc';
}
}
}
$newseq .= "
";
return $newseq;
}
/************************************************************************
* This function customizes the view of the chado_feature node. It allows
* us to generate the markup.
*/
function chado_feature_view ($node, $teaser = FALSE, $page = FALSE) {
if (!$teaser) {
// use drupal's default node view:
$node = node_prepare($node, $teaser);
// if we're building the node for searching then
// we want to handle this within the module and
// not allow theme customization. We don't want to
// index all items (such as DNA sequence).
if($node->build_mode == NODE_BUILD_SEARCH_INDEX){
$node->content['index_version'] = array(
'#value' => theme('tripal_feature_search_index',$node),
'#weight' => 1,
);
}
else if($node->build_mode == NODE_BUILD_SEARCH_RESULT){
$node->content['index_version'] = array(
'#value' => theme('tripal_feature_search_results',$node),
'#weight' => 1,
);
}
else {
// do nothing here, let the theme derived template handle display
}
}
return $node;
}
/*******************************************************************************
* Display feature information for associated organisms. This function also
* provides contents for indexing
*/
function tripal_feature_nodeapi(&$node, $op, $teaser, $page) {
switch ($op) {
// Note that this function only adds feature view to an organism node.
// The view of a feature node is controled by the theme *.tpl file
case 'view':
// Set the node types for showing feature information
$types_to_show = array('chado_organism', 'chado_library');
// Abort if this node is not one of the types we should show.
if (!in_array($node->type, $types_to_show, TRUE)) {
break;
}
// Add feature to the content item if it's not a teaser
if (!$teaser) {
// Show feature browser
$node->content['tripal_feature_browser'] = array(
'#value' => theme('tripal_feature_browser', $node),
'#weight' => 5
);
$node->content['tripal_feature_org_counts'] = array(
'#value' => theme('tripal_feature_counts', $node),
'#weight' => 4
);
}
}
}
/************************************************************************
* We need to let drupal know about our theme functions and their arguments.
* We create theme functions to allow users of the module to customize the
* look and feel of the output generated in this module
*/
function tripal_feature_theme () {
return array(
'tripal_feature_search_index' => array (
'arguments' => array('node'),
),
'tripal_feature_search_results' => array (
'arguments' => array('node'),
),
'tripal_feature_browser' => array (
'arguments' => array('node'),
),
'tripal_feature_counts' => array (
'arguments' => array('node'),
)
);
}
/*******************************************************************************
* create a list of features for the organism and pie chart
*/
function theme_tripal_feature_counts($node){
// don't show the summary if the settings in the admin page is turned off
$show_browser = variable_get('tripal_feature_summary_setting',array('show_feature_summary'));
if(strcmp($show_browser[0],'show_feature_summary')!=0){
return;
}
// get the feature counts. This is dependent on a materialized view
// installed with the organism module
$content = '';
if ($node->organism_id && $node->type == 'chado_organism') {
$sql = "SELECT * FROM {organism_feature_count} ".
"WHERE organism_id = %d AND NOT feature_type = 'EST_match' ".
"ORDER BY num_features desc";
$features = array();
$previous_db = tripal_db_set_active('chado'); // use chado database
$results = db_query($sql,$node->organism_id);
tripal_db_set_active($previous_db); // now use drupal database
$feature = db_fetch_object($results); // retrieve the first result
if ($feature) {
$content .= "