|
@@ -1,2319 +0,0 @@
|
|
|
-<?php
|
|
|
-/**
|
|
|
- * @file
|
|
|
- * Provides gff3 loading functionality. Creates features based on their specification
|
|
|
- * in a GFF3 file.
|
|
|
- */
|
|
|
-
|
|
|
-/**
|
|
|
- * @defgroup gff3_loader GFF3 Feature Loader
|
|
|
- * @ingroup tripal_chado
|
|
|
- * @{
|
|
|
- * Provides gff3 loading functionality. Creates features based on their specification in a GFF3 file.
|
|
|
- * @}
|
|
|
- */
|
|
|
-
|
|
|
-/**
|
|
|
- * The form to submit a GFF3 loading job
|
|
|
- *
|
|
|
- * @ingroup gff3_loader
|
|
|
- */
|
|
|
-function tripal_feature_gff3_load_form() {
|
|
|
-
|
|
|
- $form['gff_file']= array(
|
|
|
- '#type' => 'textfield',
|
|
|
- '#title' => t('GFF3 File'),
|
|
|
- '#description' => t('Please enter the full system path for the GFF file, or a path within the Drupal
|
|
|
- installation (e.g. /sites/default/files/xyz.gff). The path must be accessible to the
|
|
|
- server on which this Drupal instance is running.'),
|
|
|
- '#required' => TRUE,
|
|
|
- );
|
|
|
- // get the list of organisms
|
|
|
- $sql = "SELECT * FROM {organism} ORDER BY genus, species";
|
|
|
- $org_rset = chado_query($sql);
|
|
|
- $organisms = array();
|
|
|
- $organisms[''] = '';
|
|
|
- while ($organism = $org_rset->fetchObject()) {
|
|
|
- $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 to which these sequences are associated"),
|
|
|
- '#required' => TRUE,
|
|
|
- '#options' => $organisms,
|
|
|
- );
|
|
|
-
|
|
|
- // get the list of analyses
|
|
|
- $sql = "SELECT * FROM {analysis} ORDER BY name";
|
|
|
- $org_rset = chado_query($sql);
|
|
|
- $analyses = array();
|
|
|
- $analyses[''] = '';
|
|
|
- while ($analysis = $org_rset->fetchObject()) {
|
|
|
- $analyses[$analysis->analysis_id] = "$analysis->name ($analysis->program $analysis->programversion, $analysis->sourcename)";
|
|
|
- }
|
|
|
- $form['analysis_id'] = array(
|
|
|
- '#title' => t('Analysis'),
|
|
|
- '#type' => t('select'),
|
|
|
- '#description' => t("Choose the analysis to which these features are associated.
|
|
|
- Why specify an analysis for a data load? All data comes
|
|
|
- from some place, even if downloaded from Genbank. By specifying
|
|
|
- analysis details for all data imports it allows an end user to reproduce the
|
|
|
- data set, but at least indicates the source of the data."),
|
|
|
- '#required' => TRUE,
|
|
|
- '#options' => $analyses,
|
|
|
- );
|
|
|
-
|
|
|
- $form['line_number']= array(
|
|
|
- '#type' => 'textfield',
|
|
|
- '#title' => t('Start Line Number'),
|
|
|
- '#description' => t('Enter the line number in the GFF file where you would like to begin processing. The
|
|
|
- first line is line number 1. This option is useful for examining loading problems with large GFF files.'),
|
|
|
- '#size' => 10,
|
|
|
- );
|
|
|
-
|
|
|
- $form['landmark_type'] = array(
|
|
|
- '#title' => t('Landmark Type'),
|
|
|
- '#type' => t('textfield'),
|
|
|
- '#description' => t("Optional. Use this field to specify a Sequence Ontology type
|
|
|
- for the landmark sequences in the GFF fie (e.g. 'chromosome'). If the GFF file
|
|
|
- contains a '##sequence-region' line that describes the landmark sequences to
|
|
|
- which all others are aligned and a type is provided here then the features
|
|
|
- will be created if they do not already exist. If they do exist then this
|
|
|
- field is not used."),
|
|
|
- );
|
|
|
-
|
|
|
- $form['alt_id_attr'] = array(
|
|
|
- '#title' => t('ID Attribute'),
|
|
|
- '#type' => t('textfield'),
|
|
|
- '#description' => t("Optional. Sometimes lines in the GFF file are missing the
|
|
|
- required ID attribute that specifies the unique name of the feature, but there
|
|
|
- may be another attribute that can uniquely identify the feature. If so,
|
|
|
- you may specify the name of the attribute to use for the name."),
|
|
|
- );
|
|
|
-
|
|
|
- // Advanced Options
|
|
|
- $form['advanced'] = array(
|
|
|
- '#type' => 'fieldset',
|
|
|
- '#title' => t('Advanced Options'),
|
|
|
- '#collapsible' => TRUE,
|
|
|
- '#collapsed' => TRUE,
|
|
|
- );
|
|
|
-
|
|
|
- $form['advanced']['protein_names'] = array(
|
|
|
- '#type' => 'fieldset',
|
|
|
- '#title' => t('Protein Names'),
|
|
|
- '#collapsible' => TRUE,
|
|
|
- '#collapsed' => FALSE,
|
|
|
- '#weight' => 5,
|
|
|
- );
|
|
|
-
|
|
|
- $form['advanced']['protein_names']['re_help'] = array(
|
|
|
- '#type' => 'item',
|
|
|
- '#markup' => t('A regular expression is an advanced method for extracting information from a string of text.
|
|
|
- If your GFF3 file does not contain polypeptide (or protein) features, but contains CDS features, proteins will be automatically created.
|
|
|
- By default the loader will give each protein a name based on the name of the corresponding mRNA followed by the "-protein" suffix.
|
|
|
- If you want to customize the name of the created protein, you can use the following regex.')
|
|
|
- );
|
|
|
- $form['advanced']['protein_names']['re_mrna'] = array(
|
|
|
- '#type' => 'textfield',
|
|
|
- '#title' => t('Regular expression for the mRNA name'),
|
|
|
- '#required' => FALSE,
|
|
|
- '#description' => t('Enter the regular expression that will extract portions of
|
|
|
- the mRNA unique name. For example, for a
|
|
|
- mRNA with a unique name finishing by -RX (e.g. SPECIES0000001-RA),
|
|
|
- the regular expression would be, "^(.*?)-R([A-Z]+)$".')
|
|
|
- );
|
|
|
- $form['advanced']['protein_names']['re_protein'] = array(
|
|
|
- '#type' => 'textfield',
|
|
|
- '#title' => t('Replacement string for the protein name'),
|
|
|
- '#required' => FALSE,
|
|
|
- '#description' => t('Enter the replacement string that will be used to create
|
|
|
- the protein name based on the mRNA regular expression. For example, for a
|
|
|
- mRNA regular expression "^(.*?)-R()[A-Z]+)$", the corresponding protein regular
|
|
|
- expression would be "$1-P$2".')
|
|
|
- );
|
|
|
-
|
|
|
- $form['advanced']['import_options'] = array(
|
|
|
- '#type' => 'fieldset',
|
|
|
- '#title' => t('Import Options'),
|
|
|
- '#collapsible' => TRUE,
|
|
|
- '#collapsed' => FALSE,
|
|
|
- '#weight' => 0,
|
|
|
- );
|
|
|
-
|
|
|
- $form['advanced']['import_options']['use_transaction']= array(
|
|
|
- '#type' => 'checkbox',
|
|
|
- '#title' => t('Use a transaction'),
|
|
|
- '#required' => FALSE,
|
|
|
- '#description' => t('Use a database transaction when loading the GFF file. If an error occurs
|
|
|
- the entire datset loaded prior to the failure will be rolled back and will not be available
|
|
|
- in the database. If this option is unchecked and failure occurs all records up to the point
|
|
|
- of failure will be present in the database.'),
|
|
|
- '#default_value' => 1,
|
|
|
- );
|
|
|
- $form['advanced']['import_options']['add_only']= array(
|
|
|
- '#type' => 'checkbox',
|
|
|
- '#title' => t('Import only new features'),
|
|
|
- '#required' => FALSE,
|
|
|
- '#description' => t('The job will skip features in the GFF file that already
|
|
|
- exist in the database and import only new features.'),
|
|
|
- );
|
|
|
- $form['advanced']['import_options']['update']= array(
|
|
|
- '#type' => 'checkbox',
|
|
|
- '#title' => t('Import all and update'),
|
|
|
- '#required' => FALSE,
|
|
|
- '#default_value' => 'checked',
|
|
|
- '#description' => t('Existing features will be updated and new features will be added. Attributes
|
|
|
- for a feature that are not present in the GFF but which are present in the
|
|
|
- database will not be altered.'),
|
|
|
- '#default_value' => 1,
|
|
|
- );
|
|
|
-// SPF: there are bugs in refreshing and removing features. The bugs arise
|
|
|
-// if a feature in the GFF does not have a uniquename. GenSAS will auto
|
|
|
-// generate this uniquename and it will not be the same as a previous
|
|
|
-// load because it uses the date. This causes orphaned CDS/exons, UTRs
|
|
|
-// to be left behind during a delete or refresh. So, the short term
|
|
|
-// fix is to remove these options.
|
|
|
-// $form['import_options']['refresh']= array(
|
|
|
-// '#type' => 'checkbox',
|
|
|
-// '#title' => t('Import all and replace'),
|
|
|
-// '#required' => FALSE,
|
|
|
-// '#description' => t('Existing features will be updated and feature properties not
|
|
|
-// present in the GFF file will be removed.'),
|
|
|
-// );
|
|
|
-// $form['import_options']['remove']= array(
|
|
|
-// '#type' => 'checkbox',
|
|
|
-// '#title' => t('Delete features'),
|
|
|
-// '#required' => FALSE,
|
|
|
-// '#description' => t('Features present in the GFF file that exist in the database
|
|
|
-// will be removed rather than imported'),
|
|
|
-// );
|
|
|
- $form['advanced']['import_options']['create_organism']= array(
|
|
|
- '#type' => 'checkbox',
|
|
|
- '#title' => t('Create organism'),
|
|
|
- '#required' => FALSE,
|
|
|
- '#description' => t('The Tripal GFF loader supports the "organism" attribute. This allows features of a
|
|
|
- different organism to be aligned to the landmark sequence of another species. The format of the
|
|
|
- attribute is "organism=[genus]:[species]", where [genus] is the organism\'s genus and [species] is the
|
|
|
- species name. Check this box to automatically add the organism to the database if it does not already exists.
|
|
|
- Otherwise lines with an oraganism attribute where the organism is not present in the database will be skipped.'),
|
|
|
- );
|
|
|
-
|
|
|
- $form['advanced']['targets'] = array(
|
|
|
- '#type' => 'fieldset',
|
|
|
- '#title' => t('Targets'),
|
|
|
- '#collapsible' => TRUE,
|
|
|
- '#collapsed' => FALSE,
|
|
|
- '#weight' => 1,
|
|
|
- );
|
|
|
- $form['advanced']['targets']['adesc'] = array(
|
|
|
- '#markup' => t("When alignments are represented in the GFF file (e.g. such as
|
|
|
- alignments of cDNA sequences to a whole genome, or blast matches), they are
|
|
|
- represented using two feature types: 'match' (or cDNA_match, EST_match, etc.)
|
|
|
- and 'match_part'. These features may also have a 'Target' attribute to
|
|
|
- specify the sequence that is being aligned.
|
|
|
- However, the organism to which the aligned sequence belongs may not be present in the
|
|
|
- GFF file. Here you can specify the organism and feature type of the target sequences.
|
|
|
- The options here will apply to all targets unless the organism and type are explicity
|
|
|
- set in the GFF file using the 'target_organism' and 'target_type' attributes."),
|
|
|
- );
|
|
|
- $form['advanced']['targets']['target_organism_id'] = array(
|
|
|
- '#title' => t('Target Organism'),
|
|
|
- '#type' => t('select'),
|
|
|
- '#description' => t("Optional. Choose the organism to which target sequences belong.
|
|
|
- Select this only if target sequences belong to a different organism than the
|
|
|
- one specified above. And only choose an organism here if all of the target sequences
|
|
|
- belong to the same species. If the targets in the GFF file belong to multiple
|
|
|
- different species then the organism must be specified using the 'target_organism=genus:species'
|
|
|
- attribute in the GFF file."),
|
|
|
- '#options' => $organisms,
|
|
|
- );
|
|
|
- $form['advanced']['targets']['target_type'] = array(
|
|
|
- '#title' => t('Target Type'),
|
|
|
- '#type' => t('textfield'),
|
|
|
- '#description' => t("Optional. If the unique name for a target sequence is not unique (e.g. a protein
|
|
|
- and an mRNA have the same name) then you must specify the type for all targets in the GFF file. If
|
|
|
- the targets are of different types then the type must be specified using the 'target_type=type' attribute
|
|
|
- in the GFF file. This must be a valid Sequence Ontology (SO) term."),
|
|
|
- );
|
|
|
- $form['advanced']['targets']['create_target']= array(
|
|
|
- '#type' => 'checkbox',
|
|
|
- '#title' => t('Create Target'),
|
|
|
- '#required' => FALSE,
|
|
|
- '#description' => t("If the target feature cannot be found, create one using the organism and type specified above, or
|
|
|
- using the 'target_organism' and 'target_type' fields specified in the GFF file. Values specified in the
|
|
|
- GFF file take precedence over those specified above."),
|
|
|
- );
|
|
|
-
|
|
|
- $form['button'] = array(
|
|
|
- '#type' => 'submit',
|
|
|
- '#value' => t('Import GFF3 file'),
|
|
|
- '#weight' => 10,
|
|
|
- );
|
|
|
-
|
|
|
- return $form;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Validate the GFF3 loading job form
|
|
|
- *
|
|
|
- * @ingroup gff3_loader
|
|
|
- */
|
|
|
-function tripal_feature_gff3_load_form_validate($form, &$form_state) {
|
|
|
-
|
|
|
- $gff_file = trim($form_state['values']['gff_file']);
|
|
|
- $organism_id = $form_state['values']['organism_id'];
|
|
|
- $target_organism_id = $form_state['values']['target_organism_id'];
|
|
|
- $target_type = trim($form_state['values']['target_type']);
|
|
|
- $create_target = $form_state['values']['create_target'];
|
|
|
- $create_organism = $form_state['values']['create_organism'];
|
|
|
- $add_only = $form_state['values']['add_only'];
|
|
|
- $update = $form_state['values']['update'];
|
|
|
- $refresh = 0; //$form_state['values']['refresh'];
|
|
|
- $remove = 0; //$form_state['values']['remove'];
|
|
|
- $use_transaction = $form_state['values']['use_transaction'];
|
|
|
- $line_number = trim($form_state['values']['line_number']);
|
|
|
- $landmark_type = trim($form_state['values']['landmark_type']);
|
|
|
- $alt_id_attr = trim($form_state['values']['alt_id_attr']);
|
|
|
- $re_mrna = trim($form_state['values']['re_mrna']);
|
|
|
- $re_protein = trim($form_state['values']['re_protein']);
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- // check to see if the file is located local to Drupal
|
|
|
- $gff_file = trim($gff_file);
|
|
|
- $dfile = $_SERVER['DOCUMENT_ROOT'] . base_path() . $gff_file;
|
|
|
- if (!file_exists($dfile)) {
|
|
|
- // if not local to Drupal, the file must be someplace else, just use
|
|
|
- // the full path provided
|
|
|
- $dfile = $gff_file;
|
|
|
- }
|
|
|
- if (!file_exists($dfile)) {
|
|
|
- form_set_error('gff_file', t("Cannot find the file on the system. Check that the file exists or that the web server has permissions to read the file."));
|
|
|
- }
|
|
|
-
|
|
|
- // @coder-ignore: there are no functions being called here
|
|
|
- if (($add_only AND ($update OR $refresh OR $remove)) OR
|
|
|
- ($update AND ($add_only OR $refresh OR $remove)) OR
|
|
|
- ($refresh AND ($update OR $add_only OR $remove)) OR
|
|
|
- ($remove AND ($update OR $refresh OR $add_only))) {
|
|
|
- form_set_error('add_only', t("Please select only one checkbox from the import options section"));
|
|
|
- }
|
|
|
-
|
|
|
- if ($line_number and !is_numeric($line_number) or $line_number < 0) {
|
|
|
- form_set_error('line_number', t("Please provide an integer line number greater than zero."));
|
|
|
- }
|
|
|
-
|
|
|
- if (!($re_mrna and $re_protein) and ($re_mrna or $re_protein)) {
|
|
|
- form_set_error('re_uname', t("You must provide both a regular expression for mRNA and a replacement string for protein"));
|
|
|
- }
|
|
|
-
|
|
|
- // check the regular expression to make sure it is valid
|
|
|
- set_error_handler(function() {}, E_WARNING);
|
|
|
- $result_re = preg_match("/" . $re_mrna . "/", null);
|
|
|
- $result = preg_replace("/" . $re_mrna . "/", $re_protein, null);
|
|
|
- restore_error_handler();
|
|
|
- if ($result_re === FALSE) {
|
|
|
- form_set_error('re_mrna', 'Invalid regular expression.');
|
|
|
- } else if ($result === FALSE) {
|
|
|
- form_set_error('re_protein', 'Invalid replacement string.');
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Submit the GFF3 loading job
|
|
|
- *
|
|
|
- * @ingroup gff3_loader
|
|
|
- */
|
|
|
-function tripal_feature_gff3_load_form_submit($form, &$form_state) {
|
|
|
- global $user;
|
|
|
-
|
|
|
- $gff_file = trim($form_state['values']['gff_file']);
|
|
|
- $organism_id = $form_state['values']['organism_id'];
|
|
|
- $add_only = $form_state['values']['add_only'];
|
|
|
- $update = $form_state['values']['update'];
|
|
|
- $refresh = 0; //$form_state['values']['refresh'];
|
|
|
- $remove = 0; //$form_state['values']['remove'];
|
|
|
- $analysis_id = $form_state['values']['analysis_id'];
|
|
|
- $use_transaction = $form_state['values']['use_transaction'];
|
|
|
- $target_organism_id = $form_state['values']['target_organism_id'];
|
|
|
- $target_type = trim($form_state['values']['target_type']);
|
|
|
- $create_target = $form_state['values']['create_target'];
|
|
|
- $line_number = trim($form_state['values']['line_number']);
|
|
|
- $landmark_type = trim($form_state['values']['landmark_type']);
|
|
|
- $alt_id_attr = trim($form_state['values']['alt_id_attr']);
|
|
|
- $create_organism = $form_state['values']['create_organism'];
|
|
|
- $re_mrna = trim($form_state['values']['re_mrna']);
|
|
|
- $re_protein = trim($form_state['values']['re_protein']);
|
|
|
-
|
|
|
-
|
|
|
- $args = array($gff_file, $organism_id, $analysis_id, $add_only,
|
|
|
- $update, $refresh, $remove, $use_transaction, $target_organism_id,
|
|
|
- $target_type, $create_target, $line_number, $landmark_type, $alt_id_attr,
|
|
|
- $create_organism, $re_mrna, $re_protein);
|
|
|
-
|
|
|
- $type = '';
|
|
|
- if ($add_only) {
|
|
|
- $type = 'import only new features';
|
|
|
- }
|
|
|
- if ($update) {
|
|
|
- $type = 'import all and update';
|
|
|
- }
|
|
|
- if ($refresh) {
|
|
|
- $type = 'import all and replace';
|
|
|
- }
|
|
|
- if ($remove) {
|
|
|
- $type = 'delete features';
|
|
|
- }
|
|
|
- $fname = preg_replace("/.*\/(.*)/", "$1", $gff_file);
|
|
|
- $includes = array(
|
|
|
- module_load_include('inc', 'tripal_chado', 'includes/loaders/tripal_chado.gff_loader'),
|
|
|
- );
|
|
|
- tripal_add_job("$type GFF3 file: $fname", 'tripal_chado',
|
|
|
- 'tripal_feature_load_gff3', $args, $user->uid, 10, $includes);
|
|
|
-
|
|
|
- return '';
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Actually load a GFF3 file. This is the function called by tripal jobs
|
|
|
- *
|
|
|
- * @param $gff_file
|
|
|
- * The full path to the GFF file on the filesystem
|
|
|
- * @param $organism_id
|
|
|
- * The organism_id of the organism to which the features in the GFF belong
|
|
|
- * @param $analysis_id
|
|
|
- * The anlaysis_id of the analysis from which the features in the GFF were generated
|
|
|
- * @param $add_only
|
|
|
- * Set to 1 if feature should be added only. In the case where a feature
|
|
|
- * already exists, it will not be updated. Default is 0
|
|
|
- * @param $update
|
|
|
- * Set to 1 to update existing features. New features will be added. Attributes
|
|
|
- * for a feature that are not present in the GFF but which are present in the
|
|
|
- * database will not be altered. Default is 1
|
|
|
- * @param $refresh
|
|
|
- * Set to 1 to update existing features. New features will be added. Attributes
|
|
|
- * for a feature that are not present in the GFF but which are present in the
|
|
|
- * database will be removed. Default is 0
|
|
|
- * @param $remove
|
|
|
- * Set to 1 to remove features present in the GFF file that exist in the database.
|
|
|
- * Default is 0.
|
|
|
- * @param $use_transaction
|
|
|
- * Set to 1 to use a transaction when loading the GFF. Any failure during
|
|
|
- * loading will result in the rollback of any changes. Default is 1.
|
|
|
- * @param $target_organism_id
|
|
|
- * If the GFF file contains a 'Target' attribute then the feature and the
|
|
|
- * target will have an alignment created, but to find the proper target
|
|
|
- * feature the target organism must also be known. If different from the
|
|
|
- * organism specified for the GFF file, then use this argument to specify
|
|
|
- * the target organism. Only use this argument if all target sequences belong
|
|
|
- * to the same species. If the targets in the GFF file belong to multiple
|
|
|
- * different species then the organism must be specified using the
|
|
|
- * 'target_organism=genus:species' attribute in the GFF file. Default is NULL.
|
|
|
- * @param $target_type
|
|
|
- * If the GFF file contains a 'Target' attribute then the feature and the
|
|
|
- * target will have an alignment created, but to find the proper target
|
|
|
- * feature the target organism must also be known. This can be used to
|
|
|
- * specify the target feature type to help with identification of the target
|
|
|
- * feature. Only use this argument if all target sequences types are the same.
|
|
|
- * If the targets are of different types then the type must be specified using
|
|
|
- * the 'target_type=type' attribute in the GFF file. This must be a valid
|
|
|
- * Sequence Ontology (SO) term. Default is NULL
|
|
|
- * @param $create_target
|
|
|
- * Set to 1 to create the target feature if it cannot be found in the
|
|
|
- * database. Default is 0
|
|
|
- * @param $start_line
|
|
|
- * Set this to the line in the GFF file where importing should start. This
|
|
|
- * is useful for testing and debugging GFF files that may have problems and
|
|
|
- * you want to start at a particular line to speed testing. Default = 1
|
|
|
- * @param $landmark_type
|
|
|
- * Use this argument to specify a Sequence Ontology term name for the landmark
|
|
|
- * sequences in the GFF fie (e.g. 'chromosome'), if the GFF file contains a
|
|
|
- * '##sequence-region' line that describes the landmark sequences. Default = ''
|
|
|
- * @param $alt_id_attr
|
|
|
- * Sometimes lines in the GFF file are missing the required ID attribute that
|
|
|
- * specifies the unique name of the feature. If so, you may specify the
|
|
|
- * name of an existing attribute to use for the ID.
|
|
|
- * @param $create_organism
|
|
|
- * The Tripal GFF loader supports the "organism" attribute. This allows
|
|
|
- * features of a different organism to be aligned to the landmark sequence of
|
|
|
- * another species. The format of the attribute is "organism=[genus]:[species]",
|
|
|
- * where [genus] is the organism's genus and [species] is the species name.
|
|
|
- * Check this box to automatically add the organism to the database if it does
|
|
|
- * not already exists. Otherwise lines with an oraganism attribute where the
|
|
|
- * organism is not present in the database will be skipped.
|
|
|
- * @param $re_mrna A
|
|
|
- * regular expression to extract portions from mRNA id
|
|
|
- * @param $re_protein A
|
|
|
- * replacement string to generate the protein id
|
|
|
- * @param $job
|
|
|
- * The tripal job_id. Only used by the Tripal Jobs subsystem.
|
|
|
- *
|
|
|
- * @ingroup gff3_loader
|
|
|
- */
|
|
|
-function tripal_feature_load_gff3($gff_file, $organism_id, $analysis_id,
|
|
|
- $add_only = 0, $update = 1, $refresh = 0, $remove = 0, $use_transaction = 1,
|
|
|
- $target_organism_id = NULL, $target_type = NULL, $create_target = 0,
|
|
|
- $start_line = 1, $landmark_type = '', $alt_id_attr = '', $create_organism = FALSE,
|
|
|
- $re_mrna = '', $re_protein = '', $job = NULL) {
|
|
|
-
|
|
|
- $ret = array();
|
|
|
- $date = getdate();
|
|
|
-
|
|
|
- // An array that stores CVterms that have been looked up so we don't have
|
|
|
- // to do the database query every time.
|
|
|
- $cvterm_lookup = array();
|
|
|
-
|
|
|
- // An array that stores Landmarks that have been looked up so we don't have
|
|
|
- // to do the database query every time.
|
|
|
- $landmark_lookup = array();
|
|
|
-
|
|
|
- // empty the temp tables
|
|
|
- $sql = "DELETE FROM {tripal_gff_temp}";
|
|
|
- chado_query($sql);
|
|
|
- $sql = "DELETE FROM {tripal_gffcds_temp}";
|
|
|
- chado_query($sql);
|
|
|
- $sql = "DELETE FROM {tripal_gffprotein_temp}";
|
|
|
- chado_query($sql);
|
|
|
-
|
|
|
- // begin the transaction
|
|
|
- $transaction = null;
|
|
|
- if ($use_transaction) {
|
|
|
- $transaction = db_transaction();
|
|
|
- print "\nNOTE: Loading of this GFF file is performed using a database transaction. \n" .
|
|
|
- "If the load fails or is terminated prematurely then the entire set of \n" .
|
|
|
- "insertions/updates is rolled back and will not be found in the database\n\n";
|
|
|
- }
|
|
|
- try {
|
|
|
-
|
|
|
- // check to see if the file is located local to Drupal
|
|
|
- $dfile = $_SERVER['DOCUMENT_ROOT'] . base_path() . $gff_file;
|
|
|
- if (!file_exists($dfile)) {
|
|
|
- // if not local to Drupal, the file must be someplace else, just use
|
|
|
- // the full path provided
|
|
|
- $dfile = $gff_file;
|
|
|
- }
|
|
|
- if (!file_exists($dfile)) {
|
|
|
- tripal_report_error('tripal_chado', TRIPAL_ERROR, "Cannot find the file: %dfile",
|
|
|
- array('%dfile' => $dfile));
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
- print "Opening $gff_file\n";
|
|
|
-
|
|
|
- //$lines = file($dfile,FILE_SKIP_EMPTY_LINES);
|
|
|
- $fh = fopen($dfile, 'r');
|
|
|
- if (!$fh) {
|
|
|
- tripal_report_error('tripal_chado', TRIPAL_ERROR, "cannot open file: %dfile",
|
|
|
- array('%dfile' => $dfile));
|
|
|
- return 0;
|
|
|
- }
|
|
|
- $filesize = filesize($dfile);
|
|
|
-
|
|
|
- // get the controlled vocaubulary that we'll be using. The
|
|
|
- // default is the 'sequence' ontology
|
|
|
- $sql = "SELECT * FROM {cv} WHERE name = :cvname";
|
|
|
- $cv = chado_query($sql, array(':cvname' => 'sequence'))->fetchObject();
|
|
|
- if (!$cv) {
|
|
|
- tripal_report_error('tripal_chado', TRIPAL_ERROR,
|
|
|
- "Cannot find the 'sequence' ontology", array());
|
|
|
- return '';
|
|
|
- }
|
|
|
- // get the organism for which this GFF3 file belongs
|
|
|
- $sql = "SELECT * FROM {organism} WHERE organism_id = :organism_id";
|
|
|
- $organism = chado_query($sql, array(':organism_id' => $organism_id))->fetchObject();
|
|
|
-
|
|
|
- $interval = intval($filesize * 0.0001);
|
|
|
- if ($interval == 0) {
|
|
|
- $interval = 1;
|
|
|
- }
|
|
|
- $in_fasta = 0;
|
|
|
- $line_num = 0;
|
|
|
- $num_read = 0;
|
|
|
- $intv_read = 0;
|
|
|
-
|
|
|
- // prepare the statement used to get the cvterm for each feature.
|
|
|
- $sel_cvterm_sql = "
|
|
|
- SELECT CVT.cvterm_id, CVT.cv_id, CVT.name, CVT.definition,
|
|
|
- CVT.dbxref_id, CVT.is_obsolete, CVT.is_relationshiptype
|
|
|
- FROM {cvterm} CVT
|
|
|
- INNER JOIN {cv} CV on CVT.cv_id = CV.cv_id
|
|
|
- LEFT JOIN {cvtermsynonym} CVTS on CVTS.cvterm_id = CVT.cvterm_id
|
|
|
- WHERE CV.cv_id = :cv_id and
|
|
|
- (lower(CVT.name) = lower(:name) or lower(CVTS.synonym) = lower(:synonym))
|
|
|
- ";
|
|
|
-
|
|
|
- // If a landmark type was provided then pre-retrieve that.
|
|
|
- if ($landmark_type) {
|
|
|
- $query = array(
|
|
|
- ':cv_id' => $cv->cv_id,
|
|
|
- ':name' => $landmark_type,
|
|
|
- ':synonym' => $landmark_type
|
|
|
- );
|
|
|
- $result = chado_query($sel_cvterm_sql, $query);
|
|
|
- $landmark_cvterm = $result->fetchObject();
|
|
|
- if (!$landmark_cvterm) {
|
|
|
- tripal_report_error('tripal_chado', TRIPAL_ERROR,
|
|
|
- 'cannot find landmark feature type \'%landmark_type\'.',
|
|
|
- array('%landmark_type' => $landmark_type));
|
|
|
- return '';
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // iterate through each line of the GFF file
|
|
|
- print "Parsing Line $line_num (0.00%). Memory: " . number_format(memory_get_usage()) . " bytes\r";
|
|
|
- while ($line = fgets($fh)) {
|
|
|
- $line_num++;
|
|
|
- $size = drupal_strlen($line);
|
|
|
- $num_read += $size;
|
|
|
- $intv_read += $size;
|
|
|
-
|
|
|
- if ($line_num < $start_line) {
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- // update the job status every 1% features
|
|
|
- if ($job and $intv_read >= $interval) {
|
|
|
- $intv_read = 0;
|
|
|
- $percent = sprintf("%.2f", ($num_read / $filesize) * 100);
|
|
|
- print "Parsing Line $line_num (" . $percent . "%). Memory: " . number_format(memory_get_usage()) . " bytes.\r";
|
|
|
- tripal_set_job_progress($job, intval(($num_read / $filesize) * 100));
|
|
|
- }
|
|
|
-
|
|
|
- // check to see if we have FASTA section, if so then set the variable
|
|
|
- // to start parsing
|
|
|
- if (preg_match('/^##FASTA/i', $line)) {
|
|
|
- print "Parsing FASTA portion...\n";
|
|
|
- if ($remove) {
|
|
|
- // we're done because this is a delete operation so break out of the loop.
|
|
|
- break;
|
|
|
- }
|
|
|
- tripal_feature_load_gff3_fasta($fh, $interval, $num_read, $intv_read, $line_num, $filesize, $job);
|
|
|
- continue;
|
|
|
- }
|
|
|
- // if the ##sequence-region line is present then we want to add a new feature
|
|
|
- if (preg_match('/^##sequence-region (.*?) (\d+) (\d+)$/i', $line, $region_matches)) {
|
|
|
- $rid = $region_matches[1];
|
|
|
- $rstart = $region_matches[2];
|
|
|
- $rend = $region_matches[3];
|
|
|
- if ($landmark_type) {
|
|
|
- tripal_feature_load_gff3_feature($organism, $analysis_id, $landmark_cvterm, $rid,
|
|
|
- $rid, '', 'f', 'f', 1, 0);
|
|
|
- }
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- // skip comments
|
|
|
- if (preg_match('/^#/', $line)) {
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- // skip empty lines
|
|
|
- if (preg_match('/^\s*$/', $line)) {
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- // get the columns
|
|
|
- $cols = explode("\t", $line);
|
|
|
- if (sizeof($cols) != 9) {
|
|
|
- tripal_report_error('tripal_chado', TRIPAL_ERROR, 'improper number of columns on line %line_num',
|
|
|
- array('%line_num' => $line_num));
|
|
|
- return '';
|
|
|
- }
|
|
|
-
|
|
|
- // get the column values
|
|
|
- $landmark = $cols[0];
|
|
|
- $source = $cols[1];
|
|
|
- $type = $cols[2];
|
|
|
- $start = $cols[3];
|
|
|
- $end = $cols[4];
|
|
|
- $score = $cols[5];
|
|
|
- $strand = $cols[6];
|
|
|
- $phase = $cols[7];
|
|
|
- $attrs = explode(";", $cols[8]); // split by a semicolon
|
|
|
-
|
|
|
- // ready the start and stop for chado. Chado expects these positions
|
|
|
- // to be zero-based, so we substract 1 from the fmin
|
|
|
- $fmin = $start - 1;
|
|
|
- $fmax = $end;
|
|
|
- if ($end < $start) {
|
|
|
- $fmin = $end - 1;
|
|
|
- $fmax = $start;
|
|
|
- }
|
|
|
-
|
|
|
- // format the strand for chado
|
|
|
- if (strcmp($strand, '.') == 0) {
|
|
|
- $strand = 0;
|
|
|
- }
|
|
|
- elseif (strcmp($strand, '+') == 0) {
|
|
|
- $strand = 1;
|
|
|
- }
|
|
|
- elseif (strcmp($strand, '-') == 0) {
|
|
|
- $strand = -1;
|
|
|
- }
|
|
|
- if (strcmp($phase, '.') == 0) {
|
|
|
- $phase = '';
|
|
|
- }
|
|
|
- if (array_key_exists($type, $cvterm_lookup)) {
|
|
|
- $cvterm = $cvterm_lookup[$type];
|
|
|
- }
|
|
|
- else {
|
|
|
- $result = chado_query($sel_cvterm_sql, array(':cv_id' => $cv->cv_id, ':name' => $type, ':synonym' => $type));
|
|
|
- $cvterm = $result->fetchObject();
|
|
|
- $cvterm_lookup[$type] = $cvterm;
|
|
|
- if (!$cvterm) {
|
|
|
- tripal_report_error('tripal_chado', TRIPAL_ERROR, 'cannot find feature term \'%type\' on line %line_num of the GFF file',
|
|
|
- array('%type' => $type, '%line_num' => $line_num));
|
|
|
- return '';
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // break apart each of the attributes
|
|
|
- $tags = array();
|
|
|
- $attr_name = '';
|
|
|
- $attr_uniquename = '';
|
|
|
- $attr_residue_info = '';
|
|
|
- $attr_locgroup = 0;
|
|
|
- $attr_fmin_partial = 'f';
|
|
|
- $attr_fmax_partial = 'f';
|
|
|
- $attr_is_obsolete = 'f';
|
|
|
- $attr_is_analysis = 'f';
|
|
|
- $attr_others = [];
|
|
|
- $residues = '';
|
|
|
-
|
|
|
- // the organism to which a feature belongs can be set in the GFF
|
|
|
- // file using the 'organism' attribute. By default we
|
|
|
- // set the $feature_organism variable to the default organism for the landmark
|
|
|
- $attr_organism = '';
|
|
|
- $feature_organism = $organism;
|
|
|
-
|
|
|
- foreach ($attrs as $attr) {
|
|
|
- $attr = rtrim($attr);
|
|
|
- $attr = ltrim($attr);
|
|
|
- if (strcmp($attr, '')==0) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- if (!preg_match('/^[^\=]+\=.+$/', $attr)) {
|
|
|
- tripal_report_error('tripal_chado', TRIPAL_ERROR, 'Attribute is not correctly formatted on line %line_num: %attr',
|
|
|
- array('%line_num' => $line_num, '%attr' => $attr));
|
|
|
- return '';
|
|
|
- }
|
|
|
-
|
|
|
- // break apart each tag
|
|
|
- $tag = preg_split("/=/", $attr, 2); // split by equals sign
|
|
|
-
|
|
|
- // multiple instances of an attribute are separated by commas
|
|
|
- $tag_name = $tag[0];
|
|
|
- if (!array_key_exists($tag_name, $tags)) {
|
|
|
- $tags[$tag_name] = array();
|
|
|
- }
|
|
|
- $tags[$tag_name] = array_merge($tags[$tag_name], explode(",", $tag[1])); // split by comma
|
|
|
-
|
|
|
-
|
|
|
- // replace the URL escape codes for each tag
|
|
|
- for ($i = 0; $i < count($tags[$tag_name]); $i++) {
|
|
|
- $tags[$tag_name][$i] = urldecode($tags[$tag_name][$i]);
|
|
|
- }
|
|
|
-
|
|
|
- // get the name and ID tags
|
|
|
- $skip_feature = 0; // if there is a problem with any of the attributes this variable gets set
|
|
|
- if (strcmp($tag_name, 'ID') == 0) {
|
|
|
- $attr_uniquename = urldecode($tag[1]);
|
|
|
- }
|
|
|
- elseif (strcmp($tag_name, 'Name') == 0) {
|
|
|
- $attr_name = urldecode($tag[1]);
|
|
|
- }
|
|
|
- elseif (strcmp($tag_name, 'organism') == 0) {
|
|
|
- $attr_organism = urldecode($tag[1]);
|
|
|
- $org_matches = array();
|
|
|
- if (preg_match('/^(.*?):(.*?)$/', $attr_organism, $org_matches)) {
|
|
|
- $values = array(
|
|
|
- 'genus' => $org_matches[1],
|
|
|
- 'species' => $org_matches[2],
|
|
|
- );
|
|
|
- $org = chado_select_record('organism', array("*"), $values);
|
|
|
- if (count($org) == 0) {
|
|
|
- if ($create_organism) {
|
|
|
- $feature_organism = (object) chado_insert_record('organism', $values);
|
|
|
- if (!$feature_organism) {
|
|
|
- tripal_report_error('tripal_chado', TRIPAL_ERROR, "Could not add the organism, '%org', from line %line. Skipping this line. ",
|
|
|
- array('%org' => $attr_organism, '%line' => $line_num));
|
|
|
- $skip_feature = 1;
|
|
|
- }
|
|
|
- }
|
|
|
- else {
|
|
|
- tripal_report_error('tripal_chado', TRIPAL_ERROR, "The organism attribute '%org' on line %line does not exist. Skipping this line. ",
|
|
|
- array('%org' => $attr_organism, '%line' => $line_num));
|
|
|
- $skip_feature = 1;
|
|
|
- }
|
|
|
- }
|
|
|
- else {
|
|
|
- // We found the organism in the database so use it.
|
|
|
- $feature_organism = $org[0];
|
|
|
- }
|
|
|
- }
|
|
|
- else {
|
|
|
- tripal_report_error('tripal_chado', TRIPAL_ERROR, "The organism attribute '%org' on line %line is not properly formated. It " .
|
|
|
- "should be of the form: organism=Genus:species. Skipping this line.",
|
|
|
- array('%org' => $attr_organism, '%line' => $line_num));
|
|
|
- $skip_feature = 1;
|
|
|
- }
|
|
|
- }
|
|
|
- // Get the list of non-reserved attributes.
|
|
|
- elseif (strcmp($tag_name, 'Alias') != 0 and strcmp($tag_name, 'Parent') != 0 and
|
|
|
- strcmp($tag_name, 'Target') != 0 and strcmp($tag_name, 'Gap') != 0 and
|
|
|
- strcmp($tag_name, 'Derives_from') != 0 and strcmp($tag_name, 'Note') != 0 and
|
|
|
- strcmp($tag_name, 'Dbxref') != 0 and strcmp($tag_name, 'Ontology_term') != 0 and
|
|
|
- strcmp($tag_name, 'Is_circular') != 0 and strcmp($tag_name, 'target_organism') != 0 and
|
|
|
- strcmp($tag_name, 'target_type') != 0 and strcmp($tag_name, 'organism' != 0)) {
|
|
|
- foreach ($tags[$tag_name] as $value) {
|
|
|
- $attr_others[$tag_name][] = $value;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- // If neither name nor uniquename are provided then generate one.
|
|
|
- if (!$attr_uniquename and !$attr_name) {
|
|
|
- // Check if an alternate ID field is suggested, if so, then use
|
|
|
- // that for the name.
|
|
|
- if (array_key_exists($alt_id_attr, $tags)) {
|
|
|
- $attr_uniquename = $tags[$alt_id_attr][0];
|
|
|
- $attr_name = $attr_uniquename;
|
|
|
- }
|
|
|
- // If the row has a parent then generate a uniquename using the parent name
|
|
|
- // add the date to the name in the event there are more than one child with
|
|
|
- // the same parent.
|
|
|
- elseif (array_key_exists('Parent', $tags)) {
|
|
|
- $attr_uniquename = $tags['Parent'][0] . "-$type-$landmark-" . $date[0] . ":" . ($fmin + 1) . ".." . $fmax;
|
|
|
- $attr_name = $attr_uniquename;
|
|
|
- }
|
|
|
- // Generate a unique name based on the date, type and location
|
|
|
- // and set the name to simply be the type.
|
|
|
- else {
|
|
|
- $attr_uniquename = $date[0] . "-$type-$landmark:" . ($fmin + 1) . ".." . $fmax;
|
|
|
- $attr_name = $type;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // If a name is not specified then use the unique name as the name
|
|
|
- if (strcmp($attr_name, '') == 0) {
|
|
|
- $attr_name = $attr_uniquename;
|
|
|
- }
|
|
|
-
|
|
|
- // If an ID attribute is not specified then we must generate a
|
|
|
- // unique ID. Do this by combining the attribute name with the date
|
|
|
- // and line number.
|
|
|
- if (!$attr_uniquename) {
|
|
|
- $attr_uniquename = $attr_name . '-' . $date[0] . '-' . $line_num;
|
|
|
- }
|
|
|
-
|
|
|
- // Make sure the landmark sequence exists in the database. If the user
|
|
|
- // has not specified a landmark type (and it's not required in the GFF
|
|
|
- // format) then we don't know the type of the landmark so we'll hope
|
|
|
- // that it's unique across all types for the organism. Only do this
|
|
|
- // test if the landmark and the feature are different.
|
|
|
- if (!$remove and !(strcmp($landmark, $attr_uniquename) == 0 or strcmp($landmark, $attr_name) == 0) and !in_array($landmark, $landmark_lookup)) {
|
|
|
-
|
|
|
- $select = array(
|
|
|
- 'organism_id' => $organism->organism_id,
|
|
|
- 'uniquename' => $landmark,
|
|
|
- );
|
|
|
- $columns = array('count(*) as num_landmarks');
|
|
|
- if ($landmark_type) {
|
|
|
- $select['type_id'] = array(
|
|
|
- 'name' => $landmark_type,
|
|
|
- );
|
|
|
- }
|
|
|
- $count = chado_select_record('feature', $columns, $select);
|
|
|
- if (!$count or count($count) == 0 or $count[0]->num_landmarks == 0) {
|
|
|
- // now look for the landmark using the name rather than uniquename.
|
|
|
- $select = array(
|
|
|
- 'organism_id' => $organism->organism_id,
|
|
|
- 'name' => $landmark,
|
|
|
- );
|
|
|
- $columns = array('count(*) as num_landmarks');
|
|
|
- if ($landmark_type) {
|
|
|
- $select['type_id'] = array(
|
|
|
- 'name' => $landmark_type,
|
|
|
- );
|
|
|
- }
|
|
|
- $count = chado_select_record('feature', $columns, $select);
|
|
|
- if (!$count or count($count) == 0 or $count[0]->num_landmarks == 0) {
|
|
|
- tripal_report_error('tripal_chado', TRIPAL_ERROR, "The landmark '%landmark' cannot be found for this organism (%species) " .
|
|
|
- "Please add the landmark and then retry the import of this GFF3 " .
|
|
|
- "file", array('%landmark' => $landmark, '%species' => $organism->genus . " " . $organism->species));
|
|
|
- return '';
|
|
|
- }
|
|
|
- elseif ($count[0]->num_landmarks > 1) {
|
|
|
- tripal_report_error('tripal_chado', TRIPAL_ERROR, "The landmark '%landmark' has more than one entry for this organism (%species) " .
|
|
|
- "Cannot continue", array('%landmark' => $landmark, '%species' => $organism->genus . " " . $organism->species));
|
|
|
- return '';
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
- if ($count[0]->num_landmarks > 1) {
|
|
|
- tripal_report_error('tripal_chado', TRIPAL_ERROR, "The landmark '%landmark' is not unique for this organism. " .
|
|
|
- "The features cannot be associated", array('%landmark' => $landmark));
|
|
|
- return '';
|
|
|
- }
|
|
|
-
|
|
|
- // The landmark was found, remember it
|
|
|
- $landmark_lookup[] = $landmark;
|
|
|
- }
|
|
|
-/*
|
|
|
- // If the option is to remove or refresh then we want to remove
|
|
|
- // the feature from the database.
|
|
|
- if ($remove or $refresh) {
|
|
|
- // Next remove the feature itself.
|
|
|
- $sql = "DELETE FROM {feature}
|
|
|
- WHERE organism_id = %d and uniquename = '%s' and type_id = %d";
|
|
|
- $match = array(
|
|
|
- 'organism_id' => $feature_organism->organism_id,
|
|
|
- 'uniquename' => $attr_uniquename,
|
|
|
- 'type_id' => $cvterm->cvterm_id
|
|
|
- );
|
|
|
- $result = chado_delete_record('feature', $match);
|
|
|
- if (!$result) {
|
|
|
- tripal_report_error('tripal_chado', TRIPAL_ERROR, "cannot delete feature %attr_uniquename",
|
|
|
- array('%attr_uniquename' => $attr_uniquename));
|
|
|
- }
|
|
|
- $feature = 0;
|
|
|
- unset($result);
|
|
|
- }
|
|
|
- */
|
|
|
- // Add or update the feature and all properties.
|
|
|
- if ($update or $refresh or $add_only) {
|
|
|
-
|
|
|
- // Add/update the feature.
|
|
|
- $feature = tripal_feature_load_gff3_feature($feature_organism, $analysis_id, $cvterm,
|
|
|
- $attr_uniquename, $attr_name, $residues, $attr_is_analysis,
|
|
|
- $attr_is_obsolete, $add_only, $score);
|
|
|
-
|
|
|
- if ($feature) {
|
|
|
-
|
|
|
- // Add a record for this feature to the tripal_gff_temp table for
|
|
|
- // later lookup.
|
|
|
- $values = array(
|
|
|
- 'feature_id' => $feature->feature_id,
|
|
|
- 'organism_id' => $feature->organism_id,
|
|
|
- 'type_name' => $type,
|
|
|
- 'uniquename' => $feature->uniquename
|
|
|
- );
|
|
|
- // make sure this record doesn't already exist in our temp table
|
|
|
- $results = chado_select_record('tripal_gff_temp', array('*'), $values);
|
|
|
-
|
|
|
- if (count($results) == 0) {
|
|
|
- $result = chado_insert_record('tripal_gff_temp', $values);
|
|
|
- if (!$result) {
|
|
|
- tripal_report_error('tripal_chado', TRIPAL_ERROR, "Cound not save record in temporary table, Cannot continue.", array());
|
|
|
- exit;
|
|
|
- }
|
|
|
- }
|
|
|
- // add/update the featureloc if the landmark and the ID are not the same
|
|
|
- // if they are the same then this entry in the GFF is probably a landmark identifier
|
|
|
- if (strcmp($landmark, $attr_uniquename) !=0 ) {
|
|
|
- tripal_feature_load_gff3_featureloc($feature, $organism,
|
|
|
- $landmark, $fmin, $fmax, $strand, $phase, $attr_fmin_partial,
|
|
|
- $attr_fmax_partial, $attr_residue_info, $attr_locgroup);
|
|
|
- }
|
|
|
-
|
|
|
- // add any aliases for this feature
|
|
|
- if (array_key_exists('Alias', $tags)) {
|
|
|
- tripal_feature_load_gff3_alias($feature, $tags['Alias']);
|
|
|
- }
|
|
|
- // add any dbxrefs for this feature
|
|
|
- if (array_key_exists('Dbxref', $tags)) {
|
|
|
- tripal_feature_load_gff3_dbxref($feature, $tags['Dbxref']);
|
|
|
- }
|
|
|
- // add any ontology terms for this feature
|
|
|
- if (array_key_exists('Ontology_term', $tags)) {
|
|
|
- tripal_feature_load_gff3_ontology($feature, $tags['Ontology_term']);
|
|
|
- }
|
|
|
- // add parent relationships
|
|
|
- if (array_key_exists('Parent', $tags)) {
|
|
|
- tripal_feature_load_gff3_parents($feature, $cvterm, $tags['Parent'],
|
|
|
- $feature_organism->organism_id, $strand, $phase, $fmin, $fmax);
|
|
|
- }
|
|
|
-
|
|
|
- // add target relationships
|
|
|
- if (array_key_exists('Target', $tags)) {
|
|
|
- tripal_feature_load_gff3_target($feature, $tags, $target_organism_id, $target_type, $create_target, $attr_locgroup);
|
|
|
- }
|
|
|
- // add gap information. This goes in simply as a property
|
|
|
- if (array_key_exists('Gap', $tags)) {
|
|
|
- foreach ($tags['Gap'] as $value) {
|
|
|
- tripal_feature_load_gff3_property($feature, 'Gap', $value);
|
|
|
- }
|
|
|
- }
|
|
|
- // add notes. This goes in simply as a property
|
|
|
- if (array_key_exists('Note', $tags)) {
|
|
|
- foreach ($tags['Note'] as $value) {
|
|
|
- tripal_feature_load_gff3_property($feature, 'Note', $value);
|
|
|
- }
|
|
|
- }
|
|
|
- // add the Derives_from relationship (e.g. polycistronic genes).
|
|
|
- if (array_key_exists('Derives_from', $tags)) {
|
|
|
- tripal_feature_load_gff3_derives_from($feature, $cvterm, $tags['Derives_from'][0],
|
|
|
- $feature_organism, $fmin, $fmax);
|
|
|
- }
|
|
|
- // add in the GFF3_source dbxref so that GBrowse can find the feature using the source column
|
|
|
- $source_ref = array('GFF_source:' . $source);
|
|
|
- tripal_feature_load_gff3_dbxref($feature, $source_ref);
|
|
|
- // add any additional attributes
|
|
|
- if ($attr_others) {
|
|
|
- foreach ($attr_others as $tag_name => $values) {
|
|
|
- foreach ($values as $value) {
|
|
|
- tripal_feature_load_gff3_property($feature, $tag_name, $value);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // Do some last bit of processing.
|
|
|
- if (!$remove) {
|
|
|
-
|
|
|
- // First, add any protein sequences if needed.
|
|
|
- $sql = "SELECT feature_id FROM {tripal_gffcds_temp} LIMIT 1 OFFSET 1";
|
|
|
- $has_cds = chado_query($sql)->fetchField();
|
|
|
- if ($has_cds) {
|
|
|
- print "\nAdding protein sequences if CDS exist and no proteins in GFF...\n";
|
|
|
- $sql = "
|
|
|
- SELECT F.feature_id, F.name, F.uniquename, TGCT.strand,
|
|
|
- CVT.cvterm_id, CVT.name as feature_type,
|
|
|
- min(TGCT.fmin) as fmin, max(TGCT.fmax) as fmax,
|
|
|
- TGPT.feature_id as protein_id, TGPT.fmin as protein_fmin,
|
|
|
- TGPT.fmax as protein_fmax, FLM.uniquename as landmark
|
|
|
- FROM {tripal_gffcds_temp} TGCT
|
|
|
- INNER JOIN {feature} F on F.feature_id = TGCT.parent_id
|
|
|
- INNER JOIN {cvterm} CVT on CVT.cvterm_id = F.type_id
|
|
|
- INNER JOIN {featureloc} L on F.feature_id = L.feature_id
|
|
|
- INNER JOIN {feature} FLM on L.srcfeature_id = FLM.feature_id
|
|
|
- LEFT JOIN {tripal_gffprotein_temp} TGPT on TGPT.parent_id = F.feature_id
|
|
|
- GROUP BY F.feature_id, F.name, F.uniquename, CVT.cvterm_id, CVT.name,
|
|
|
- TGPT.feature_id, TGPT.fmin, TGPT.fmax, TGCT.strand, FLM.uniquename
|
|
|
- ";
|
|
|
- $results = chado_query($sql);
|
|
|
- $protein_cvterm = tripal_get_cvterm(array(
|
|
|
- 'name' => 'polypeptide',
|
|
|
- 'cv_id' => array(
|
|
|
- 'name' => 'sequence'
|
|
|
- )
|
|
|
- ));
|
|
|
- while ($result = $results->fetchObject()) {
|
|
|
- // If a protein exists with this same parent then don't add a new
|
|
|
- // protein.
|
|
|
- if (!$result->protein_id) {
|
|
|
- // Get details about this protein
|
|
|
- if ($re_mrna and $re_protein) {
|
|
|
- // We use a regex to generate protein name from mRNA name
|
|
|
- $uname = preg_replace("/$re_mrna/", $re_protein, $result->uniquename);
|
|
|
- $name = $result->name;
|
|
|
- }
|
|
|
- else {
|
|
|
- // No regex, use the default '-protein' suffix
|
|
|
- $uname = $result->uniquename . '-protein';
|
|
|
- $name = $result->name;
|
|
|
- }
|
|
|
- $values = array(
|
|
|
- 'parent_id' => $result->feature_id,
|
|
|
- 'fmin' => $result->fmin
|
|
|
- );
|
|
|
- $min_phase = chado_select_record('tripal_gffcds_temp', array('phase'), $values);
|
|
|
- $values = array(
|
|
|
- 'parent_id' => $result->feature_id,
|
|
|
- 'fmax' => $result->fmax
|
|
|
- );
|
|
|
- $max_phase = chado_select_record('tripal_gffcds_temp', array('phase'), $values);
|
|
|
-
|
|
|
- $pfmin = $result->fmin;
|
|
|
- $pfmax = $result->fmax;
|
|
|
- if ($result->strand == '-1') {
|
|
|
- $pfmax -= $max_phase[0]->phase;
|
|
|
- }
|
|
|
- else {
|
|
|
- $pfmin += $min_phase[0]->phase;
|
|
|
- }
|
|
|
-
|
|
|
- // Add the new protein record.
|
|
|
- $feature = tripal_feature_load_gff3_feature($organism, $analysis_id,
|
|
|
- $protein_cvterm, $uname, $name, '', 'f', 'f', 1, 0);
|
|
|
- // Add the derives_from relationship.
|
|
|
- $cvterm = tripal_get_cvterm(array('cvterm_id' => $result->cvterm_id));
|
|
|
- tripal_feature_load_gff3_derives_from($feature, $cvterm,
|
|
|
- $result->uniquename, $organism, $pfmin, $pfmax);
|
|
|
- // Add the featureloc record. Set the start of the protein to
|
|
|
- // be the start of the coding sequence minus the phase.
|
|
|
- tripal_feature_load_gff3_featureloc($feature, $organism, $result->landmark,
|
|
|
- $pfmin, $pfmax, $result->strand, '', 'f', 'f', '', 0);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- print "\nSetting ranks of children...\n";
|
|
|
-
|
|
|
- // Get features in a relationship that are also children of an alignment.
|
|
|
- $sql = "
|
|
|
- SELECT DISTINCT F.feature_id, F.organism_id, F.type_id,
|
|
|
- F.uniquename, FL.strand
|
|
|
- FROM {tripal_gff_temp} TGT
|
|
|
- INNER JOIN {feature} F ON TGT.feature_id = F.feature_id
|
|
|
- INNER JOIN {feature_relationship} FR ON FR.object_id = TGT.feature_id
|
|
|
- INNER JOIN {cvterm} CVT ON CVT.cvterm_id = FR.type_id
|
|
|
- INNER JOIN {featureloc} FL ON FL.feature_id = F.feature_id
|
|
|
- WHERE CVT.name = 'part_of'
|
|
|
- ";
|
|
|
- $parents = chado_query($sql);
|
|
|
-
|
|
|
- // Build and prepare the SQL for selecting the children relationship.
|
|
|
- $sel_gffchildren_sql = "
|
|
|
- SELECT DISTINCT FR.feature_relationship_id, FL.fmin, FR.rank
|
|
|
- FROM {feature_relationship} FR
|
|
|
- INNER JOIN {featureloc} FL on FL.feature_id = FR.subject_id
|
|
|
- INNER JOIN {cvterm} CVT on CVT.cvterm_id = FR.type_id
|
|
|
- WHERE FR.object_id = :feature_id AND CVT.name = 'part_of'
|
|
|
- ORDER BY FL.fmin ASC
|
|
|
- ";
|
|
|
-
|
|
|
- // Now set the rank of any parent/child relationships. The order is based
|
|
|
- // on the fmin. The start rank is 1. This allows features with other
|
|
|
- // relationships to be '0' (the default), and doesn't interfer with the
|
|
|
- // ordering defined here.
|
|
|
- $num_recs = $parents->rowCount();
|
|
|
- $i = 1;
|
|
|
- $interval = intval($num_recs * 0.0001);
|
|
|
- if ($interval == 0) {
|
|
|
- $interval = 1;
|
|
|
- }
|
|
|
- $percent = sprintf("%.2f", ($i / $num_recs) * 100);
|
|
|
- print "Setting $i of $num_recs (" . $percent . "%). Memory: " . number_format(memory_get_usage()) . " bytes.\r";
|
|
|
-
|
|
|
- while ($parent = $parents->fetchObject()) {
|
|
|
-
|
|
|
- if ($i % $interval == 0) {
|
|
|
- $percent = sprintf("%.2f", ($i / $num_recs) * 100);
|
|
|
- print "Setting $i of $num_recs (" . $percent . "%). Memory: " . number_format(memory_get_usage()) . " bytes.\r";
|
|
|
- }
|
|
|
-
|
|
|
- // get the children
|
|
|
- $result = chado_query($sel_gffchildren_sql, array(':feature_id' => $parent->feature_id));
|
|
|
-
|
|
|
- // build an array of the children
|
|
|
- $children = array();
|
|
|
- while ($child = $result->fetchObject()) {
|
|
|
- $children[] = $child;
|
|
|
- }
|
|
|
-
|
|
|
- // the children list comes sorted in ascending fmin
|
|
|
- // but if the parent is on the reverse strand we need to
|
|
|
- // reverse the order of the children.
|
|
|
- if ($parent->strand == -1) {
|
|
|
- arsort($children);
|
|
|
- }
|
|
|
-
|
|
|
- // first set the ranks to a negative number so that we don't
|
|
|
- // get a duplicate error message when we try to change any of them
|
|
|
- $rank = -1;
|
|
|
- foreach ($children as $child) {
|
|
|
- $match = array('feature_relationship_id' => $child->feature_relationship_id);
|
|
|
- $values = array('rank' => $rank);
|
|
|
- chado_update_record('feature_relationship', $match, $values);
|
|
|
- $rank--;
|
|
|
- }
|
|
|
- // now set the rank correctly. The rank should start at 0.
|
|
|
- $rank = 0;
|
|
|
- foreach ($children as $child) {
|
|
|
- $match = array('feature_relationship_id' => $child->feature_relationship_id);
|
|
|
- $values = array('rank' => $rank);
|
|
|
- //print "Was: " . $child->rank . " now $rank ($parent->strand)\n" ;
|
|
|
- chado_update_record('feature_relationship', $match, $values);
|
|
|
- $rank++;
|
|
|
- }
|
|
|
- $i++;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- catch (Exception $e) {
|
|
|
- print "\n"; // make sure we start errors on new line
|
|
|
- if ($use_transaction) {
|
|
|
- $transaction->rollback();
|
|
|
- print "FAILED: Rolling back database changes...\n";
|
|
|
- }
|
|
|
- else {
|
|
|
- print "FAILED\n";
|
|
|
- }
|
|
|
- watchdog_exception('tripal_chado', $e);
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
- print "\nDone\n";
|
|
|
- return 1;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Load the derives from attribute for a gff3 feature
|
|
|
- *
|
|
|
- * @param $feature
|
|
|
- * @param $subject
|
|
|
- * @param $organism
|
|
|
- *
|
|
|
- * @ingroup gff3_loader
|
|
|
- */
|
|
|
-function tripal_feature_load_gff3_derives_from($feature, $cvterm, $object,
|
|
|
- $organism, $fmin, $fmax) {
|
|
|
-
|
|
|
- $type = $cvterm->name;
|
|
|
-
|
|
|
- // First look for the object feature in the temp table to get it's type.
|
|
|
- $values = array(
|
|
|
- 'organism_id' => $organism->organism_id,
|
|
|
- 'uniquename' => $object,
|
|
|
- );
|
|
|
- $result = chado_select_record('tripal_gff_temp', array('type_name'), $values);
|
|
|
- $type_id = NULL;
|
|
|
- if (count($result) > 0) {
|
|
|
- $otype = tripal_get_cvterm(array(
|
|
|
- 'name' => $result[0]->type_name,
|
|
|
- 'cv_id' => array(
|
|
|
- 'name' => 'sequence'
|
|
|
- )
|
|
|
- ));
|
|
|
- if ($otype) {
|
|
|
- $type_id = $otype->cvterm_id;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // If the object wasn't in the temp table then look for it in the
|
|
|
- // feature table and get it's type.
|
|
|
- if (!$type_id) {
|
|
|
- $result = chado_select_record('feature', array('type_id'), $values);
|
|
|
- if (count($result) > 1) {
|
|
|
- watchdog("tripal_chado", "Cannot find feature type for, '%subject' , in 'derives_from' relationship. Multiple matching features exist with this uniquename.",
|
|
|
- array('%subject' => $object), WATCHDOG_WARNING);
|
|
|
- return '';
|
|
|
- }
|
|
|
- else if (count($result) == 0) {
|
|
|
- watchdog("tripal_chado", "Cannot find feature type for, '%subject' , in 'derives_from' relationship.",
|
|
|
- array('%subject' => $object), WATCHDOG_WARNING);
|
|
|
- return '';
|
|
|
- }
|
|
|
- else {
|
|
|
- $type_id = $result->type_id;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // Get the object feature.
|
|
|
- $match = array(
|
|
|
- 'organism_id' => $organism->organism_id,
|
|
|
- 'uniquename' => $object,
|
|
|
- 'type_id' => $type_id,
|
|
|
- );
|
|
|
- $ofeature = chado_select_record('feature', array('feature_id'), $match);
|
|
|
- if (count($ofeature) == 0) {
|
|
|
- tripal_report_error('tripal_chado', TRIPAL_ERROR, "Could not add 'Derives_from' relationship " .
|
|
|
- "for %uniquename and %subject. Subject feature, '%subject', " .
|
|
|
- "cannot be found", array('%uniquename' => $feature->uniquename, '%subject' => $subject));
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // If this feature is a protein then add it to the tripal_gffprotein_temp.
|
|
|
- if ($type == 'protein' or $type == 'polypeptide') {
|
|
|
- $values = array(
|
|
|
- 'feature_id' => $feature->feature_id,
|
|
|
- 'parent_id' => $ofeature[0]->feature_id,
|
|
|
- 'fmin' => $fmin,
|
|
|
- 'fmax' => $fmax
|
|
|
- );
|
|
|
- $result = chado_insert_record('tripal_gffprotein_temp', $values);
|
|
|
- if (!$result) {
|
|
|
- tripal_report_error('tripal_chado', TRIPAL_ERROR, "Cound not save record in temporary protein table, Cannot continue.", array());
|
|
|
- exit;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // Now check to see if the relationship already exists. If it does
|
|
|
- // then just return.
|
|
|
- $values = array(
|
|
|
- 'object_id' => $ofeature[0]->feature_id,
|
|
|
- 'subject_id' => $feature->feature_id,
|
|
|
- 'type_id' => array(
|
|
|
- 'cv_id' => array(
|
|
|
- 'name' => 'sequence'
|
|
|
- ),
|
|
|
- 'name' => 'derives_from',
|
|
|
- ),
|
|
|
- 'rank' => 0
|
|
|
- );
|
|
|
- $rel = chado_select_record('feature_relationship', array('*'), $values);
|
|
|
- if (count($rel) > 0) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // finally insert the relationship if it doesn't exist
|
|
|
- $ret = chado_insert_record('feature_relationship', $values);
|
|
|
- if (!$ret) {
|
|
|
- tripal_report_error("tripal_chado", TRIPAL_WARNING, "Could not add 'Derives_from' relationship for $feature->uniquename and $subject",
|
|
|
- array());
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Load the parents for a gff3 feature
|
|
|
- *
|
|
|
- * @param $feature
|
|
|
- * @param $cvterm
|
|
|
- * @param $parents
|
|
|
- * @param $organism_id
|
|
|
- * @param $fmin
|
|
|
- *
|
|
|
- * @ingroup gff3_loader
|
|
|
- */
|
|
|
-function tripal_feature_load_gff3_parents($feature, $cvterm, $parents,
|
|
|
- $organism_id, $strand, $phase, $fmin, $fmax) {
|
|
|
-
|
|
|
- $uname = $feature->uniquename;
|
|
|
- $type = $cvterm->name;
|
|
|
- $rel_type = 'part_of';
|
|
|
-
|
|
|
- // Prepare these SQL statements that will be used repeatedly.
|
|
|
- $cvterm_sql = "
|
|
|
- SELECT CVT.cvterm_id
|
|
|
- FROM {cvterm} CVT
|
|
|
- INNER JOIN {cv} CV on CVT.cv_id = CV.cv_id
|
|
|
- LEFT JOIN {cvtermsynonym} CVTS on CVTS.cvterm_id = CVT.cvterm_id
|
|
|
- WHERE cv.name = :cvname and (CVT.name = :name or CVTS.synonym = :synonym)
|
|
|
- ";
|
|
|
-
|
|
|
- // Iterate through the parents in the list.
|
|
|
- foreach ($parents as $parent) {
|
|
|
- // Get the parent cvterm.
|
|
|
- $values = array(
|
|
|
- 'organism_id' => $organism_id,
|
|
|
- 'uniquename' => $parent,
|
|
|
- );
|
|
|
- $result = chado_select_record('tripal_gff_temp', array('type_name'), $values);
|
|
|
- if (count($result) == 0) {
|
|
|
- tripal_report_error("tripal_chado", TRIPAL_WARNING, "Cannot find parent: %parent", array('%parent' => $parent));
|
|
|
- return '';
|
|
|
- }
|
|
|
- $parent_type = $result[0]->type_name;
|
|
|
-
|
|
|
- // try to find the parent
|
|
|
- $parentcvterm = chado_query($cvterm_sql, array(':cvname' => 'sequence', ':name' => $parent_type, ':synonym' => $parent_type))->fetchObject();
|
|
|
- $relcvterm = chado_query($cvterm_sql, array(':cvname' => 'sequence', ':name' => $rel_type, ':synonym' => $rel_type))->fetchObject();
|
|
|
- if (!$relcvterm) {
|
|
|
- tripal_report_error("tripal_feature", TRIPAL_WARNING, "Cannot find the term, 'part_of', from the sequence ontology. This term is used for associating parent and children features. Please check that the ontology is fully imported.");
|
|
|
- exit;
|
|
|
- }
|
|
|
- $values = array(
|
|
|
- 'organism_id' => $organism_id,
|
|
|
- 'uniquename' => $parent,
|
|
|
- 'type_id' => $parentcvterm->cvterm_id,
|
|
|
- );
|
|
|
- $result = chado_select_record('feature', array('feature_id'), $values);
|
|
|
- $parent_feature = $result[0];
|
|
|
-
|
|
|
- // if the parent exists then add the relationship otherwise print error and skip
|
|
|
- if ($parent_feature) {
|
|
|
-
|
|
|
- // check to see if the relationship already exists
|
|
|
- $values = array(
|
|
|
- 'object_id' => $parent_feature->feature_id,
|
|
|
- 'subject_id' => $feature->feature_id,
|
|
|
- 'type_id' => $relcvterm->cvterm_id,
|
|
|
- );
|
|
|
- $rel = chado_select_record('feature_relationship', array('*'), $values);
|
|
|
-
|
|
|
- if (count($rel) > 0) {
|
|
|
- }
|
|
|
- else {
|
|
|
- // the relationship doesn't already exist, so add it.
|
|
|
- $values = array(
|
|
|
- 'subject_id' => $feature->feature_id,
|
|
|
- 'object_id' => $parent_feature->feature_id,
|
|
|
- 'type_id' => $relcvterm->cvterm_id,
|
|
|
- );
|
|
|
- $result = chado_insert_record('feature_relationship', $values);
|
|
|
- if (!$result) {
|
|
|
- tripal_report_error("tripal_chado", TRIPAL_WARNING, "Failed to insert feature relationship '$uname' ($type) $rel_type '$parent' ($parent_type)",
|
|
|
- array());
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // If this feature is a CDS and now that we know the parent we can
|
|
|
- // add it to the tripal_gffcds_temp table for later lookup.
|
|
|
- if ($type == 'CDS') {
|
|
|
- $values = array(
|
|
|
- 'feature_id' => $feature->feature_id,
|
|
|
- 'parent_id' => $parent_feature->feature_id,
|
|
|
- 'fmin' => $fmin,
|
|
|
- 'fmax' => $fmax,
|
|
|
- 'strand' => $strand,
|
|
|
- );
|
|
|
- if ($phase) {
|
|
|
- $values['phase'] = $phase;
|
|
|
- }
|
|
|
- $result = chado_insert_record('tripal_gffcds_temp', $values);
|
|
|
- if (!$result) {
|
|
|
- tripal_report_error('tripal_chado', TRIPAL_ERROR, "Cound not save record in temporary CDS table, Cannot continue.", array());
|
|
|
- exit;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- else {
|
|
|
- tripal_report_error("tripal_chado", TRIPAL_WARNING, "Cannot establish relationship '$uname' ($type) $rel_type '$parent' ($parent_type): Cannot find the parent",
|
|
|
- array());
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Load the dbxref attribute for a feature
|
|
|
- *
|
|
|
- * @param $feature
|
|
|
- * @param $dbxrefs
|
|
|
- *
|
|
|
- * @ingroup gff3_loader
|
|
|
- */
|
|
|
-function tripal_feature_load_gff3_dbxref($feature, $dbxrefs) {
|
|
|
-
|
|
|
- // iterate through each of the dbxrefs
|
|
|
- foreach ($dbxrefs as $dbxref) {
|
|
|
-
|
|
|
- // get the database name from the reference. If it doesn't exist then create one.
|
|
|
- $ref = explode(":", $dbxref);
|
|
|
- $dbname = trim($ref[0]);
|
|
|
- $accession = trim($ref[1]);
|
|
|
-
|
|
|
- // first look for the database name if it doesn't exist then create one.
|
|
|
- // first check for the fully qualified URI (e.g. DB:<dbname>. If that
|
|
|
- // can't be found then look for the name as is. If it still can't be found
|
|
|
- // the create the database
|
|
|
- $values = array('name' => "DB:$dbname");
|
|
|
- $db = chado_select_record('db', array('db_id'), $values);
|
|
|
- if (count($db) == 0) {
|
|
|
- $values = array('name' => "$dbname");
|
|
|
- $db = chado_select_record('db', array('db_id'), $values);
|
|
|
- }
|
|
|
- if (count($db) == 0) {
|
|
|
- $values = array(
|
|
|
- 'name' => $dbname,
|
|
|
- 'description' => 'Added automatically by the GFF loader'
|
|
|
- );
|
|
|
- $success = chado_insert_record('db', $values);
|
|
|
- if ($success) {
|
|
|
- $values = array('name' => "$dbname");
|
|
|
- $db = chado_select_record('db', array('db_id'), $values);
|
|
|
- }
|
|
|
- else {
|
|
|
- tripal_report_error("tripal_chado", TRIPAL_WARNING, "Cannot find or add the database $dbname", array());
|
|
|
- return 0;
|
|
|
- }
|
|
|
- }
|
|
|
- $db = $db[0];
|
|
|
-
|
|
|
- // now check to see if the accession exists
|
|
|
- $values = array(
|
|
|
- 'accession' => $accession,
|
|
|
- 'db_id' => $db->db_id
|
|
|
- );
|
|
|
- $dbxref = chado_select_record('dbxref', array('dbxref_id'), $values);
|
|
|
-
|
|
|
- // if the accession doesn't exist then we want to add it
|
|
|
- if (sizeof($dbxref) == 0) {
|
|
|
- $values = array(
|
|
|
- 'db_id' => $db->db_id,
|
|
|
- 'accession' => $accession,
|
|
|
- 'version' => ''
|
|
|
- );
|
|
|
- $ret = chado_insert_record('dbxref', $values);
|
|
|
- $values = array(
|
|
|
- 'accession' => $accession,
|
|
|
- 'db_id' => $db->db_id
|
|
|
- );
|
|
|
- $dbxref = chado_select_record('dbxref', array('dbxref_id'), $values);
|
|
|
- }
|
|
|
- $dbxref = $dbxref[0];
|
|
|
-
|
|
|
- // check to see if this feature dbxref already exists
|
|
|
- $values = array(
|
|
|
- 'dbxref_id' => $dbxref->dbxref_id,
|
|
|
- 'feature_id' => $feature->feature_id
|
|
|
- );
|
|
|
- $fdbx = chado_select_record('feature_dbxref', array('feature_dbxref_id'), $values);
|
|
|
-
|
|
|
- // now associate this feature with the database reference if it doesn't
|
|
|
- // already exist
|
|
|
- if (sizeof($fdbx) == 0) {
|
|
|
- $values = array(
|
|
|
- 'dbxref_id' => $dbxref->dbxref_id,
|
|
|
- 'feature_id' => $feature->feature_id
|
|
|
- );
|
|
|
- $success = chado_insert_record('feature_dbxref', $values);
|
|
|
- if (!$success) {
|
|
|
- tripal_report_error("tripal_chado", TRIPAL_WARNING, "Failed to insert Dbxref: $dbname:$accession", array());
|
|
|
- return 0;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return 1;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Load the cvterms for a feature. Assumes there is a dbxref.accession matching a cvterm.name
|
|
|
- *
|
|
|
- * @param $feature
|
|
|
- * @param $dbxrefs
|
|
|
- *
|
|
|
- * @ingroup gff3_loader
|
|
|
- */
|
|
|
-function tripal_feature_load_gff3_ontology($feature, $dbxrefs) {
|
|
|
-
|
|
|
- // iterate through each of the dbxrefs
|
|
|
- foreach ($dbxrefs as $dbxref) {
|
|
|
-
|
|
|
- // get the database name from the reference. If it doesn't exist then create one.
|
|
|
- $ref = explode(":", $dbxref);
|
|
|
- $dbname = trim($ref[0]);
|
|
|
- $accession = trim($ref[1]);
|
|
|
-
|
|
|
- // first look for the database name
|
|
|
- $db = chado_select_record('db', array('db_id'), array('name' => "DB:$dbname"));
|
|
|
- if (sizeof($db) == 0) {
|
|
|
- // now look for the name without the 'DB:' prefix.
|
|
|
- $db = chado_select_record('db', array('db_id'), array('name' => "$dbname"));
|
|
|
- if (sizeof($db) == 0) {
|
|
|
- tripal_report_error("tripal_chado", TRIPAL_WARNING, "Database, $dbname, is not present. Cannot associate term: $dbname:$accession", array());
|
|
|
- return 0;
|
|
|
- }
|
|
|
- }
|
|
|
- $db = $db[0];
|
|
|
-
|
|
|
- // now check to see if the accession exists
|
|
|
- $dbxref = chado_select_record('dbxref', array('dbxref_id'),
|
|
|
- array('accession' => $accession, 'db_id' => $db->db_id));
|
|
|
- if (sizeof($dbxref) == 0) {
|
|
|
- tripal_report_error("tripal_chado", TRIPAL_WARNING, "Accession, $accession is missing for reference: $dbname:$accession", array());
|
|
|
- return 0;
|
|
|
- }
|
|
|
- $dbxref = $dbxref[0];
|
|
|
-
|
|
|
- // now check to see if the cvterm exists
|
|
|
- $cvterm = chado_select_record('cvterm', array('cvterm_id'), array(
|
|
|
- 'dbxref_id' => $dbxref->dbxref_id));
|
|
|
- // if it doesn't exist in the cvterm table, look for an alternate id
|
|
|
- if (sizeof($cvterm) == 0) {
|
|
|
- $cvterm = chado_select_record('cvterm_dbxref', array('cvterm_id'), array(
|
|
|
- 'dbxref_id' => $dbxref->dbxref_id));
|
|
|
- if (sizeof($cvterm) == 0) {
|
|
|
- tripal_report_error("tripal_chado", TRIPAL_WARNING, "CV Term is missing for reference: $dbname:$accession", array());
|
|
|
- return 0;
|
|
|
- }
|
|
|
- }
|
|
|
- $cvterm = $cvterm[0];
|
|
|
-
|
|
|
-
|
|
|
- // check to see if this feature cvterm already exists
|
|
|
- $fcvt = chado_select_record('feature_cvterm', array('feature_cvterm_id'),
|
|
|
- array('cvterm_id' => $cvterm->cvterm_id, 'feature_id' => $feature->feature_id));
|
|
|
-
|
|
|
- // now associate this feature with the cvterm if it doesn't already exist
|
|
|
- if (sizeof($fcvt)==0) {
|
|
|
- $values = array(
|
|
|
- 'cvterm_id' => $cvterm->cvterm_id,
|
|
|
- 'feature_id' => $feature->feature_id,
|
|
|
- 'pub_id' => array(
|
|
|
- 'uniquename' => 'null',
|
|
|
- ),
|
|
|
- );
|
|
|
- $success = chado_insert_record('feature_cvterm', $values);
|
|
|
-
|
|
|
- if (!$success) {
|
|
|
- tripal_report_error("tripal_chado", TRIPAL_WARNING, "Failed to insert ontology term: $dbname:$accession", array());
|
|
|
- return 0;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return 1;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Load any aliases for a feature
|
|
|
- *
|
|
|
- * @param $feature
|
|
|
- * @param $aliases
|
|
|
- *
|
|
|
- * @ingroup gff3_loader
|
|
|
- */
|
|
|
-function tripal_feature_load_gff3_alias($feature, $aliases) {
|
|
|
-
|
|
|
- // make sure we have a 'synonym_type' vocabulary
|
|
|
- $select = array('name' => 'synonym_type');
|
|
|
- $results = chado_select_record('cv', array('*'), $select);
|
|
|
-
|
|
|
- if (count($results) == 0) {
|
|
|
- // insert the 'synonym_type' vocabulary
|
|
|
- $values = array(
|
|
|
- 'name' => 'synonym_type',
|
|
|
- 'definition' => 'vocabulary for synonym types',
|
|
|
- );
|
|
|
- $success = chado_insert_record('cv', $values);
|
|
|
- if (!$success) {
|
|
|
- tripal_report_error("tripal_chado", TRIPAL_WARNING, "Failed to add the synonyms type vocabulary", array());
|
|
|
- return 0;
|
|
|
- }
|
|
|
- // now that we've added the cv we need to get the record
|
|
|
- $results = chado_select_record('cv', array('*'), $select);
|
|
|
- if (count($results) > 0) {
|
|
|
- $syncv = $results[0];
|
|
|
- }
|
|
|
- }
|
|
|
- else {
|
|
|
- $syncv = $results[0];
|
|
|
- }
|
|
|
-
|
|
|
- // get the 'exact' cvterm, which is the type of synonym we're adding
|
|
|
- $select = array(
|
|
|
- 'name' => 'exact',
|
|
|
- 'cv_id' => array(
|
|
|
- 'name' => 'synonym_type'
|
|
|
- ),
|
|
|
- );
|
|
|
- $result = chado_select_record('cvterm', array('*'), $select);
|
|
|
- if (count($result) == 0) {
|
|
|
- $term = array(
|
|
|
- 'name' => 'exact',
|
|
|
- 'id' => "synonym_type:exact",
|
|
|
- 'definition' => '',
|
|
|
- 'is_obsolete' => 0,
|
|
|
- 'cv_name' => $syncv->name,
|
|
|
- 'is_relationship' => FALSE
|
|
|
- );
|
|
|
- $syntype = tripal_insert_cvterm($term, array('update_existing' => TRUE));
|
|
|
- if (!$syntype) {
|
|
|
- tripal_report_error("tripal_chado", TRIPAL_WARNING, "Cannot add synonym type: internal:$type", array());
|
|
|
- return 0;
|
|
|
- }
|
|
|
- }
|
|
|
- else {
|
|
|
- $syntype = $result[0];
|
|
|
- }
|
|
|
-
|
|
|
- // iterate through all of the aliases and add each one
|
|
|
- foreach ($aliases as $alias) {
|
|
|
-
|
|
|
- // check to see if the alias already exists in the synonym table
|
|
|
- // if not, then add it
|
|
|
- $select = array(
|
|
|
- 'name' => $alias,
|
|
|
- 'type_id' => $syntype->cvterm_id,
|
|
|
- );
|
|
|
- $result = chado_select_record('synonym', array('*'), $select);
|
|
|
- if (count($result) == 0) {
|
|
|
- $values = array(
|
|
|
- 'name' => $alias,
|
|
|
- 'type_id' => $syntype->cvterm_id,
|
|
|
- 'synonym_sgml' => '',
|
|
|
- );
|
|
|
- $success = chado_insert_record('synonym', $values);
|
|
|
- if (!$success) {
|
|
|
- tripal_report_error("tripal_chado", TRIPAL_WARNING, "Cannot add alias $alias to synonym table", array());
|
|
|
- return 0;
|
|
|
- }
|
|
|
- $result = chado_select_record('synonym', array('*'), $select);
|
|
|
- $synonym = $result[0];
|
|
|
- }
|
|
|
- else {
|
|
|
- $synonym = $result[0];
|
|
|
- }
|
|
|
-
|
|
|
- // check to see if we have a NULL publication in the pub table. If not,
|
|
|
- // then add one.
|
|
|
- $select = array('uniquename' => 'null');
|
|
|
- $result = chado_select_record('pub', array('*'), $select);
|
|
|
- if (count($result) == 0) {
|
|
|
- $pub_sql = "
|
|
|
- INSERT INTO {pub} (uniquename,type_id)
|
|
|
- VALUES (:uname,
|
|
|
- (SELECT cvterm_id
|
|
|
- FROM {cvterm} CVT
|
|
|
- INNER JOIN {dbxref} DBX ON DBX.dbxref_id = CVT.dbxref_id
|
|
|
- INNER JOIN {db} DB ON DB.db_id = DBX.db_id
|
|
|
- WHERE CVT.name = :type_id))
|
|
|
- ";
|
|
|
- $status = chado_query($psql);
|
|
|
- if (!$status) {
|
|
|
- tripal_report_error("tripal_chado", TRIPAL_WARNING, "Cannot prepare statement 'ins_pub_uniquename_typeid", array());
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
- // insert the null pub
|
|
|
- $result = chado_query($pub_sql, array(':uname' => 'null', ':type_id' => 'null'))->fetchObject();
|
|
|
- if (!$result) {
|
|
|
- tripal_report_error("tripal_chado", TRIPAL_WARNING, "Cannot add null publication needed for setup of alias", array());
|
|
|
- return 0;
|
|
|
- }
|
|
|
- $result = chado_select_record('pub', array('*'), $select);
|
|
|
- $pub = $result[0];
|
|
|
- }
|
|
|
- else {
|
|
|
- $pub = $result[0];
|
|
|
- }
|
|
|
-
|
|
|
- // check to see if the synonym exists in the feature_synonym table
|
|
|
- // if not, then add it.
|
|
|
- $values = array(
|
|
|
- 'synonym_id' => $synonym->synonym_id,
|
|
|
- 'feature_id' => $feature->feature_id,
|
|
|
- 'pub_id' => $pub->pub_id,
|
|
|
- );
|
|
|
- $columns = array('feature_synonym_id');
|
|
|
- $result = chado_select_record('feature_synonym', $columns, $values);
|
|
|
- if (count($result) == 0) {
|
|
|
- $values = array(
|
|
|
- 'synonym_id' => $synonym->synonym_id,
|
|
|
- 'feature_id' => $feature->feature_id,
|
|
|
- 'pub_id' => $pub->pub_id,
|
|
|
- );
|
|
|
- $success = chado_insert_record('feature_synonym', $values);
|
|
|
-
|
|
|
- if (!$success) {
|
|
|
- tripal_report_error("tripal_chado", TRIPAL_WARNING, "Cannot add alias $alias to feature synonym table", array());
|
|
|
- return 0;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return 1;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Create the feature record & link it to it's analysis
|
|
|
- *
|
|
|
- * @param $organism
|
|
|
- * @param $analysis_id
|
|
|
- * @param $cvterm
|
|
|
- * @param $uniquename
|
|
|
- * @param $name
|
|
|
- * @param $residues
|
|
|
- * @param $is_analysis
|
|
|
- * @param $is_obsolete
|
|
|
- * @param $add_only
|
|
|
- * @param $score
|
|
|
- *
|
|
|
- * @ingroup gff3_loader
|
|
|
- */
|
|
|
-function tripal_feature_load_gff3_feature($organism, $analysis_id, $cvterm, $uniquename,
|
|
|
- $name, $residues, $is_analysis = 'f', $is_obsolete = 'f', $add_only, $score) {
|
|
|
-
|
|
|
- // Check to see if the feature already exists.
|
|
|
- $feature = NULL;
|
|
|
- $fselect = array(
|
|
|
- 'organism_id' => $organism->organism_id,
|
|
|
- 'uniquename' => $uniquename,
|
|
|
- 'type_id' => $cvterm->cvterm_id
|
|
|
- );
|
|
|
- $columns = array('feature_id', 'name', 'uniquename', 'seqlen', 'organism_id', 'type_id');
|
|
|
- $result = chado_select_record('feature', $columns, $fselect);
|
|
|
- if (count($result) > 0) {
|
|
|
- $feature = $result[0];
|
|
|
- }
|
|
|
-
|
|
|
- if (strcmp($is_obsolete, 'f')==0 or $is_obsolete == 0) {
|
|
|
- $is_obsolete = 'FALSE';
|
|
|
- }
|
|
|
- if (strcmp($is_obsolete, 't')==0 or $is_obsolete == 1) {
|
|
|
- $is_obsolete = 'TRUE';
|
|
|
- }
|
|
|
- if (strcmp($is_analysis, 'f')==0 or $is_analysis == 0) {
|
|
|
- $is_analysis = 'FALSE';
|
|
|
- }
|
|
|
- if (strcmp($is_analysis, 't')==0 or $is_analysis == 1) {
|
|
|
- $is_analysis = 'TRUE';
|
|
|
- }
|
|
|
-
|
|
|
- // Insert the feature if it does not exist otherwise perform an update.
|
|
|
- if (!$feature) {
|
|
|
- $values = array(
|
|
|
- 'organism_id' => $organism->organism_id,
|
|
|
- 'name' => $name,
|
|
|
- 'uniquename' => $uniquename,
|
|
|
- 'md5checksum' => md5($residues),
|
|
|
- 'type_id' => $cvterm->cvterm_id,
|
|
|
- 'is_analysis' => $is_analysis,
|
|
|
- 'is_obsolete' => $is_obsolete,
|
|
|
- );
|
|
|
- $feature = (object) chado_insert_record('feature', $values);
|
|
|
- if (!$feature) {
|
|
|
- tripal_report_error("tripal_chado", TRIPAL_WARNING, "Failed to insert feature '$uniquename' ($cvterm->name)", array());
|
|
|
- return 0;
|
|
|
- }
|
|
|
- }
|
|
|
- elseif (!$add_only) {
|
|
|
- $values = array(
|
|
|
- 'name' => $name,
|
|
|
- 'md5checksum' => md5($residues),
|
|
|
- 'is_analysis' => $is_analysis,
|
|
|
- 'is_obsolete' => $is_obsolete,
|
|
|
- );
|
|
|
- $match = array(
|
|
|
- 'organism_id' => $organism->organism_id,
|
|
|
- 'uniquename' => $uniquename,
|
|
|
- 'type_id' => $cvterm->cvterm_id,
|
|
|
- );
|
|
|
- $result = chado_update_record('feature', $match, $values);
|
|
|
- if (!$result) {
|
|
|
- tripal_report_error("tripal_chado", TRIPAL_WARNING, "Failed to update feature '$uniquename' ($cvterm->name)", array());
|
|
|
- return 0;
|
|
|
- }
|
|
|
- }
|
|
|
- else {
|
|
|
- // The feature exists and we don't want to update it so return
|
|
|
- // a value of 0. This will stop all downstream property additions
|
|
|
- return $feature;
|
|
|
- }
|
|
|
-
|
|
|
- // Add the analysisfeature entry to the analysisfeature table if
|
|
|
- // it doesn't already exist.
|
|
|
- $af_values = array(
|
|
|
- 'analysis_id' => $analysis_id,
|
|
|
- 'feature_id' => $feature->feature_id
|
|
|
- );
|
|
|
- $afeature = chado_select_record('analysisfeature', array('analysisfeature_id'), $af_values);
|
|
|
- if (count($afeature)==0) {
|
|
|
- // if a score is available then set that to be the significance field
|
|
|
- if (strcmp($score, '.') != 0) {
|
|
|
- $af_values['significance'] = $score;
|
|
|
- }
|
|
|
- if (!chado_insert_record('analysisfeature', $af_values)) {
|
|
|
- tripal_report_error("tripal_chado", TRIPAL_WARNING, "Could not add analysisfeature record: $analysis_id, $feature->feature_id", array());
|
|
|
- }
|
|
|
- }
|
|
|
- else {
|
|
|
- // if a score is available then set that to be the significance field
|
|
|
- $new_vals = array();
|
|
|
- if (strcmp($score, '.')!=0) {
|
|
|
- $new_vals['significance'] = $score;
|
|
|
- }
|
|
|
- else {
|
|
|
- $new_vals['significance'] = '__NULL__';
|
|
|
- }
|
|
|
- if (!$add_only) {
|
|
|
- $ret = chado_update_record('analysisfeature', $af_values, $new_vals);
|
|
|
- if (!$ret) {
|
|
|
- tripal_report_error("tripal_chado", TRIPAL_WARNING, "Could not update analysisfeature record: $analysis_id, $feature->feature_id", array());
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return $feature;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Insert the location of the feature
|
|
|
- *
|
|
|
- * @param $feature
|
|
|
- * @param $organism
|
|
|
- * @param $landmark
|
|
|
- * @param $fmin
|
|
|
- * @param $fmax
|
|
|
- * @param $strand
|
|
|
- * @param $phase
|
|
|
- * @param $is_fmin_partial
|
|
|
- * @param $is_fmax_partial
|
|
|
- * @param $residue_info
|
|
|
- * @param $locgroup
|
|
|
- * @param $landmark_type_id
|
|
|
- * @param $landmark_organism_id
|
|
|
- * @param $create_landmark
|
|
|
- * @param $landmark_is_target
|
|
|
- *
|
|
|
- * @ingroup gff3_loader
|
|
|
- */
|
|
|
-function tripal_feature_load_gff3_featureloc($feature, $organism, $landmark, $fmin,
|
|
|
- $fmax, $strand, $phase, $is_fmin_partial, $is_fmax_partial, $residue_info, $locgroup,
|
|
|
- $landmark_type_id = '', $landmark_organism_id = '', $create_landmark = 0,
|
|
|
- $landmark_is_target = 0) {
|
|
|
-
|
|
|
- $select = array(
|
|
|
- 'organism_id' => $landmark_organism_id ? $landmark_organism_id : $organism->organism_id,
|
|
|
- 'uniquename' => $landmark,
|
|
|
- );
|
|
|
- if ($landmark_type_id) {
|
|
|
- $select['type_id'] = $landmark_type_id;
|
|
|
- }
|
|
|
- $results = chado_select_record('feature', array('feature_id'), $select);
|
|
|
-
|
|
|
- $srcfeature = '';
|
|
|
- if (count($results)==0) {
|
|
|
- // so we couldn't find the landmark using the uniquename. Let's try the 'name'.
|
|
|
- // if we return only a single result then we can proceed. Otherwise give an
|
|
|
- $select = array(
|
|
|
- 'organism_id' => $landmark_organism_id ? $landmark_organism_id : $organism->organism_id,
|
|
|
- 'name' => $landmark,
|
|
|
- );
|
|
|
- if ($landmark_type_id) {
|
|
|
- $select['type_id'] = $landmark_type_id;
|
|
|
- }
|
|
|
- $results = chado_select_record('feature', array('feature_id'), $select);
|
|
|
- if (count($results) == 0) {
|
|
|
- // if the landmark is the target feature in a matched alignment then try one more time to
|
|
|
- // find it by querying any feature with the same uniquename. If we find one then use it.
|
|
|
- if ($landmark_is_target) {
|
|
|
- $select = array('uniquename' => $landmark);
|
|
|
- $results = chado_select_record('feature', array('feature_id'), $select);
|
|
|
- if (count($results) == 1) {
|
|
|
- $srcfeature = $results[0];
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (!$srcfeature) {
|
|
|
- // we couldn't find the landmark feature, so if the user has requested we create it then do so
|
|
|
- // but only if we have a type id
|
|
|
- if ($create_landmark and $landmark_type_id) {
|
|
|
- $values = array(
|
|
|
- 'organism_id' => $landmark_organism_id ? $landmark_organism_id : $organism->organism_id,
|
|
|
- 'name' => $landmark,
|
|
|
- 'uniquename' => $landmark,
|
|
|
- 'type_id' => $landmark_type_id
|
|
|
- );
|
|
|
- $results = chado_insert_record('feature', $values);
|
|
|
- if (!$results) {
|
|
|
- tripal_report_error("tripal_chado", TRIPAL_WARNING, "Cannot find landmark feature: '%landmark', nor could it be inserted",
|
|
|
- array('%landmark' => $landmark));
|
|
|
- return 0;
|
|
|
- }
|
|
|
- $srcfeature = new stdClass();
|
|
|
- $srcfeature->feature_id = $results['feature_id'];
|
|
|
- }
|
|
|
- else {
|
|
|
- tripal_report_error("tripal_chado", TRIPAL_WARNING, "Cannot find unique landmark feature: '%landmark'.",
|
|
|
- array('%landmark' => $landmark));
|
|
|
- return 0;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- elseif (count($results) > 1) {
|
|
|
- tripal_report_error("tripal_chado", TRIPAL_WARNING, "multiple landmarks exist with the name: '%landmark'. Cannot
|
|
|
- resolve which one to use. Cannot add the feature location record",
|
|
|
- array('%landmark' => $landmark));
|
|
|
- return 0;
|
|
|
- }
|
|
|
- else {
|
|
|
- $srcfeature = $results[0];
|
|
|
- }
|
|
|
- }
|
|
|
- elseif (count($results) > 1) {
|
|
|
- tripal_report_error("tripal_chado", TRIPAL_WARNING, "multiple landmarks exist with the name: '%landmark'. Cannot
|
|
|
- resolve which one to use. Cannot add the feature location record",
|
|
|
- array('%landmark' => $landmark));
|
|
|
- return 0;
|
|
|
- }
|
|
|
- else {
|
|
|
- $srcfeature = $results[0];
|
|
|
- }
|
|
|
-
|
|
|
- // TODO: create an attribute that recognizes the residue_info,locgroup,
|
|
|
- // is_fmin_partial and is_fmax_partial, right now these are
|
|
|
- // hardcoded to be false and 0 below.
|
|
|
-
|
|
|
- // check to see if this featureloc already exists, but also keep track of the
|
|
|
- // last rank value
|
|
|
- $rank = 0;
|
|
|
- $exists = 0;
|
|
|
- $select = array('feature_id' => $feature->feature_id);
|
|
|
- $options = array(
|
|
|
- 'order_by' => array(
|
|
|
- 'rank' => 'ASC'
|
|
|
- ),
|
|
|
- );
|
|
|
-
|
|
|
- $locrecs = chado_select_record('featureloc', array('*'), $select, $options);
|
|
|
-
|
|
|
- foreach ($locrecs as $featureloc) {
|
|
|
- // it is possible for the featureloc->srcfeature_id to be NULL. This can happen if the srcfeature
|
|
|
- // is not known (according to chado table field descriptions). If it's null then just skip this entry
|
|
|
- if (!$featureloc->srcfeature_id) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- $select = array('feature_id' => $featureloc->srcfeature_id);
|
|
|
- $columns = array('feature_id', 'name');
|
|
|
- $locsfeature = chado_select_record('feature', $columns, $select);
|
|
|
-
|
|
|
- // the source feature name and at least the fmin and fmax must be the same
|
|
|
- // for an update of the featureloc, otherwise we'll insert a new record.
|
|
|
- if (strcmp($locsfeature[0]->name, $landmark)==0 and
|
|
|
- ($featureloc->fmin == $fmin or $featureloc->fmax == $fmax)) {
|
|
|
- $match = array('featureloc_id' => $featureloc->featureloc_id);
|
|
|
- $values = array();
|
|
|
- $exists = 1;
|
|
|
- if ($featureloc->fmin != $fmin) {
|
|
|
- $values['fmin'] = $fmin;
|
|
|
- }
|
|
|
- if ($featureloc->fmax != $fmax) {
|
|
|
- $values['fmax'] = $fmax;
|
|
|
- }
|
|
|
- if ($featureloc->strand != $strand) {
|
|
|
- $values['strand'] = $strand;
|
|
|
- }
|
|
|
- if (count($values) > 0) {
|
|
|
- chado_update_record('featureloc', $match, $values);
|
|
|
- }
|
|
|
- }
|
|
|
- $rank = $featureloc->rank + 1;
|
|
|
- }
|
|
|
- if (!$exists) {
|
|
|
-
|
|
|
- // this feature location is new so add it
|
|
|
- if (strcmp($is_fmin_partial, 'f')==0 or !$is_fmin_partial) {
|
|
|
- $is_fmin_partial = 'FALSE';
|
|
|
- }
|
|
|
- elseif (strcmp($is_fmin_partial, 't')==0 or $is_fmin_partial = 1) {
|
|
|
- $is_fmin_partial = 'TRUE';
|
|
|
- }
|
|
|
- if (strcmp($is_fmax_partial, 'f')==0 or !$is_fmax_partial) {
|
|
|
- $is_fmax_partial = 'FALSE';
|
|
|
- }
|
|
|
- elseif (strcmp($is_fmax_partial, 't')==0 or $is_fmax_partial = 1) {
|
|
|
- $is_fmax_partial = 'TRUE';
|
|
|
- }
|
|
|
- $values = array(
|
|
|
- 'feature_id' => $feature->feature_id,
|
|
|
- 'srcfeature_id' => $srcfeature->feature_id,
|
|
|
- 'fmin' => $fmin,
|
|
|
- 'is_fmin_partial' => $is_fmin_partial,
|
|
|
- 'fmax' => $fmax,
|
|
|
- 'is_fmax_partial' => $is_fmax_partial,
|
|
|
- 'strand' => $strand,
|
|
|
- 'residue_info' => $residue_info,
|
|
|
- 'locgroup' => $locgroup,
|
|
|
- 'rank' => $rank
|
|
|
- );
|
|
|
- if ($phase) {
|
|
|
- $values['phase'] = $phase;
|
|
|
- }
|
|
|
- $success = chado_insert_record('featureloc', $values);
|
|
|
- if (!$success) {
|
|
|
- tripal_report_error("tripal_chado", TRIPAL_WARNING, "Failed to insert featureloc", array());
|
|
|
- exit;
|
|
|
- return 0;
|
|
|
- }
|
|
|
- }
|
|
|
- return 1;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Load a preoprty (featurepop) for the feature
|
|
|
- *
|
|
|
- * @param $feature
|
|
|
- * @param $property
|
|
|
- * @param $value
|
|
|
- *
|
|
|
- * @ingroup gff3_loader
|
|
|
- */
|
|
|
-function tripal_feature_load_gff3_property($feature, $property, $value) {
|
|
|
-
|
|
|
- // first make sure the cvterm exists. if not, then add it
|
|
|
- $select = array(
|
|
|
- 'name' => $property,
|
|
|
- 'cv_id' => array(
|
|
|
- 'name' => 'feature_property',
|
|
|
- ),
|
|
|
- );
|
|
|
- $result = chado_select_record('cvterm', array('*'), $select);
|
|
|
-
|
|
|
- // if we don't have a property like this already, then add it otherwise, just return
|
|
|
- if (count($result) == 0) {
|
|
|
- $term = array(
|
|
|
- 'id' => "null:$property",
|
|
|
- 'name' => $property,
|
|
|
- 'namespace' => 'feature_property',
|
|
|
- 'is_obsolete' => 0,
|
|
|
- 'cv_name' => 'feature_property',
|
|
|
- 'is_relationship' => FALSE
|
|
|
- );
|
|
|
- $cvterm = (object) tripal_insert_cvterm($term, array('update_existing' => FALSE));
|
|
|
- if (!$cvterm) {
|
|
|
- tripal_report_error("tripal_chado", TRIPAL_WARNING, "Cannot add cvterm, $property", array());
|
|
|
- return 0;
|
|
|
- }
|
|
|
- }
|
|
|
- else {
|
|
|
- $cvterm = $result[0];
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- // check to see if the property already exists for this feature
|
|
|
- // if it does but the value is unique then increment the rank and add it.
|
|
|
- // if the value is not unique then don't add it.
|
|
|
- $add = 1;
|
|
|
- $rank = 0;
|
|
|
- $select = array(
|
|
|
- 'feature_id' => $feature->feature_id,
|
|
|
- 'type_id' => $cvterm->cvterm_id,
|
|
|
- );
|
|
|
- $options = array(
|
|
|
- 'order_by' => array(
|
|
|
- 'rank' => 'ASC',
|
|
|
- ),
|
|
|
- );
|
|
|
- $results = chado_select_record('featureprop', array('*'), $select, $options);
|
|
|
- foreach ($results as $prop) {
|
|
|
- if (strcmp($prop->value, $value)==0) {
|
|
|
- $add = NULL; // don't add it, it already exists
|
|
|
- }
|
|
|
- $rank = $prop->rank + 1;
|
|
|
- }
|
|
|
-
|
|
|
- // add the property if we pass the check above
|
|
|
- if ($add) {
|
|
|
- $values = array(
|
|
|
- 'feature_id' => $feature->feature_id,
|
|
|
- 'type_id' => $cvterm->cvterm_id,
|
|
|
- 'value' => $value,
|
|
|
- 'rank' => $rank,
|
|
|
- );
|
|
|
- $result = chado_insert_record('featureprop', $values);
|
|
|
- if (!$result) {
|
|
|
- tripal_report_error("tripal_chado", TRIPAL_WARNING, "cannot add featureprop, $property", array());
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Load the FASTA sequences at the bottom of a GFF3 file
|
|
|
- *
|
|
|
- * @param $fh
|
|
|
- * @param $interval
|
|
|
- * @param $num_read
|
|
|
- * @param $intv_read
|
|
|
- * @param $line_num
|
|
|
- * @param $filesize
|
|
|
- * @param $job
|
|
|
- *
|
|
|
- * @ingroup gff3_loader
|
|
|
- */
|
|
|
-function tripal_feature_load_gff3_fasta($fh, $interval, &$num_read, &$intv_read, &$line_num, $filesize, $job) {
|
|
|
- print "\nLoading FASTA sequences\n";
|
|
|
- $residues = '';
|
|
|
- $id = NULL;
|
|
|
-
|
|
|
- $percent = sprintf("%.2f", ($num_read / $filesize) * 100);
|
|
|
- print "Parsing Line $line_num (" . $percent . "%). Memory: " . number_format(memory_get_usage()) . " bytes.\r";
|
|
|
- // iterate through the remaining lines of the file
|
|
|
- while ($line = fgets($fh)) {
|
|
|
-
|
|
|
- $line_num++;
|
|
|
- $size = drupal_strlen($line);
|
|
|
- $num_read += $size;
|
|
|
- $intv_read += $size;
|
|
|
-
|
|
|
- $line = trim($line);
|
|
|
-
|
|
|
- // update the job status every 1% features
|
|
|
- if ($job and $intv_read >= $interval) {
|
|
|
- $intv_read = 0;
|
|
|
- $percent = sprintf("%.2f", ($num_read / $filesize) * 100);
|
|
|
- print "Parsing Line $line_num (" . $percent . "%). Memory: " . number_format(memory_get_usage()) . " bytes.\r";
|
|
|
- tripal_set_job_progress($job, intval(($num_read / $filesize) * 100));
|
|
|
- }
|
|
|
-
|
|
|
- // if we encounter a definition line then get the name, uniquename,
|
|
|
- // accession and relationship subject from the definition line
|
|
|
- if (preg_match('/^>/', $line)) {
|
|
|
-
|
|
|
- // if we are beginning a new sequence then save to the database the last one we just finished.
|
|
|
- if ($id) {
|
|
|
- $values = array('uniquename' => $id);
|
|
|
- $result = chado_select_record('tripal_gff_temp', array('*'), $values);
|
|
|
- if (count($result) == 0) {
|
|
|
- tripal_report_error('tripal_chado', TRIPAL_WARNING, 'Cannot find feature to assign FASTA sequence: %uname',
|
|
|
- array('%uname' => $id));
|
|
|
- }
|
|
|
- else {
|
|
|
- // if we have a feature then add the residues
|
|
|
- $feature = $result[0];
|
|
|
- $values = array(
|
|
|
- 'residues' => $residues,
|
|
|
- 'seqlen' => strlen($residues)
|
|
|
- );
|
|
|
- $match = array('feature_id' => $feature->feature_id);
|
|
|
- chado_update_record('feature', $match, $values);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // get the feature ID for this ID from the tripal_gff_temp table. It
|
|
|
- // should be the name up to the first space
|
|
|
- $id = preg_replace('/^>([^\s]+).*$/', '\1', $line);
|
|
|
- $residues = '';
|
|
|
- }
|
|
|
- else {
|
|
|
- $residues .= trim($line);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // add in the last sequence
|
|
|
- $values = array('uniquename' => $id);
|
|
|
- $result = chado_select_record('tripal_gff_temp', array('*'), $values);
|
|
|
- if (count($result) == 0) {
|
|
|
- tripal_report_error('tripal_chado', TRIPAL_WARNING, 'Cannot find feature to assign FASTA sequence: %uname',
|
|
|
- array('%uname' => $id));
|
|
|
- }
|
|
|
- else {
|
|
|
- // if we have a feature then add the residues
|
|
|
- $feature = $result[0];
|
|
|
- $values = array(
|
|
|
- 'residues' => $residues,
|
|
|
- 'seqlen' => strlen($residues)
|
|
|
- );
|
|
|
- $match = array('feature_id' => $feature->feature_id);
|
|
|
- chado_update_record('feature', $match, $values);
|
|
|
- }
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Load the target attribute of a gff3 record
|
|
|
- *
|
|
|
- * @param $feature
|
|
|
- * @param $tags
|
|
|
- * @param $target_organism_id
|
|
|
- * @param $target_type
|
|
|
- * @param $create_target
|
|
|
- * @param $attr_locgroup
|
|
|
- *
|
|
|
- * @ingroup gff3_loader
|
|
|
- */
|
|
|
-function tripal_feature_load_gff3_target($feature, $tags, $target_organism_id, $target_type, $create_target, $attr_locgroup) {
|
|
|
- // format is: "target_id start end [strand]", where strand is optional and may be "+" or "-"
|
|
|
- $matched = preg_match('/^(.*?)\s+(\d+)\s+(\d+)(\s+[\+|\-])*$/', trim($tags['Target'][0]), $matches);
|
|
|
-
|
|
|
- // the organism and type of the target may also be specified as an attribute. If so, then get that
|
|
|
- // information
|
|
|
- $gff_target_organism = array_key_exists('target_organism', $tags) ? $tags['target_organism'][0] : '';
|
|
|
- $gff_target_type = array_key_exists('target_type', $tags) ? $tags['target_type'][0] : '';
|
|
|
-
|
|
|
- // if we have matches and the Target is in the correct format then load the alignment
|
|
|
- if ($matched) {
|
|
|
- $target_feature = $matches[1];
|
|
|
- $start = $matches[2];
|
|
|
- $end = $matches[3];
|
|
|
- // if we have an optional strand, convert it to a numeric value.
|
|
|
- if ($matches[4]) {
|
|
|
- if (preg_match('/^\+$/', trim($matches[4]))) {
|
|
|
- $target_strand = 1;
|
|
|
- }
|
|
|
- elseif (preg_match('/^\-$/', trim($matches[4]))) {
|
|
|
- $target_strand = -1;
|
|
|
- }
|
|
|
- else {
|
|
|
- $target_strand = 0;
|
|
|
- }
|
|
|
- }
|
|
|
- else {
|
|
|
- $target_strand = 0;
|
|
|
- }
|
|
|
-
|
|
|
- $target_fmin = $start - 1;
|
|
|
- $target_fmax = $end;
|
|
|
- if ($end < $start) {
|
|
|
- $target_fmin = $end - 1;
|
|
|
- $target_fmax = $start;
|
|
|
- }
|
|
|
-
|
|
|
- // default the target organism to be the value passed into the function, but if the GFF
|
|
|
- // file species the target organism then use that instead.
|
|
|
- $t_organism_id = $target_organism_id;
|
|
|
- if ($gff_target_organism) {
|
|
|
- // get the genus and species
|
|
|
- $success = preg_match('/^(.*?):(.*?)$/', $gff_target_organism, $matches);
|
|
|
- if ($success) {
|
|
|
- $values = array(
|
|
|
- 'genus' => $matches[1],
|
|
|
- 'species' => $matches[2],
|
|
|
- );
|
|
|
- $torganism = chado_select_record('organism', array('organism_id'), $values);
|
|
|
- if (count($torganism) == 1) {
|
|
|
- $t_organism_id = $torganism[0]->organism_id;
|
|
|
- }
|
|
|
- else {
|
|
|
- tripal_report_error('tripal_chado', TRIPAL_WARNING, "Cannot find organism for target %target.",
|
|
|
- array('%target' => $gff_target_organism));
|
|
|
- $t_organism_id = '';
|
|
|
- }
|
|
|
- }
|
|
|
- else {
|
|
|
- tripal_report_error('tripal_chado', TRIPAL_WARNING, "The target_organism attribute is improperly formatted: %target.
|
|
|
- It should be target_organism=genus:species.",
|
|
|
- array('%target' => $gff_target_organism));
|
|
|
- $t_organism_id = '';
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // default the target type to be the value passed into the function, but if the GFF file
|
|
|
- // species the target type then use that instead
|
|
|
- $t_type_id = '';
|
|
|
- if ($target_type) {
|
|
|
- $values = array(
|
|
|
- 'name' => $target_type,
|
|
|
- 'cv_id' => array(
|
|
|
- 'name' => 'sequence',
|
|
|
- )
|
|
|
- );
|
|
|
- $type = chado_select_record('cvterm', array('cvterm_id'), $values);
|
|
|
- if (count($type) == 1) {
|
|
|
- $t_type_id = $type[0]->cvterm_id;
|
|
|
- }
|
|
|
- else {
|
|
|
- tripal_report_error('tripal_chado', TRIPAL_ERROR, "The target type does not exist in the sequence ontology: %type. ",
|
|
|
- array('%type' => $target_type));
|
|
|
- exit;
|
|
|
- }
|
|
|
- }
|
|
|
- if ($gff_target_type) {
|
|
|
- $values = array(
|
|
|
- 'name' => $gff_target_type,
|
|
|
- 'cv_id' => array(
|
|
|
- 'name' => 'sequence',
|
|
|
- )
|
|
|
- );
|
|
|
-
|
|
|
- // get the cvterm_id for the target type
|
|
|
- $type = chado_select_record('cvterm', array('cvterm_id'), $values);
|
|
|
- if (count($type) == 1) {
|
|
|
- $t_type_id = $type[0]->cvterm_id;
|
|
|
- }
|
|
|
- else {
|
|
|
- // check to see if this is a synonym
|
|
|
- $sql = "
|
|
|
- SELECT CVTS.cvterm_id
|
|
|
- FROM {cvtermsynonym} CVTS
|
|
|
- INNER JOIN {cvterm} CVT ON CVT.cvterm_id = CVTS.cvterm_id
|
|
|
- INNER JOIN {cv} CV ON CV.cv_id = CVT.cv_id
|
|
|
- WHERE CV.name = 'sequence' and CVTS.synonym = :synonym
|
|
|
- ";
|
|
|
- $synonym = chado_query($sql, array(':synonym' => $gff_target_type))->fetchObject();
|
|
|
- if ($synonym) {
|
|
|
- $t_type_id = $synonym->cvterm_id;
|
|
|
- }
|
|
|
- else {
|
|
|
- tripal_report_error('tripal_chado', TRIPAL_WARNING, "The target_type attribute does not exist in the sequence ontology: %type. ",
|
|
|
- array('%type' => $gff_target_type));
|
|
|
- $t_type_id = '';
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // we want to add a featureloc record that uses the target feature as the srcfeature (landmark)
|
|
|
- // and the landmark as the feature.
|
|
|
- tripal_feature_load_gff3_featureloc($feature, $organism, $target_feature, $target_fmin,
|
|
|
- $target_fmax, $target_strand, $phase, $attr_fmin_partial, $attr_fmax_partial, $attr_residue_info,
|
|
|
- $attr_locgroup, $t_type_id, $t_organism_id, $create_target, TRUE);
|
|
|
- }
|
|
|
- // the target attribute is not correctly formatted
|
|
|
- else {
|
|
|
- tripal_report_error('tripal_chado', TRIPAL_ERROR, "Could not add 'Target' alignment as it is improperly formatted: '%target'",
|
|
|
- array('%target' => $tags['Target'][0]));
|
|
|
- }
|
|
|
-}
|