<commit_before>use strict;

# Sets display_xref_ids for novel genes in the "to" database based
# on their orthologs in the "from" database. Can also project GO xrefs.
# Orthology relationships are read from a Compara database.

use Getopt::Long;
use Bio::EnsEMBL::Registry;
use Bio::EnsEMBL::DBSQL::DBAdaptor;
use Bio::EnsEMBL::DBSQL::GeneAdaptor;

my $method_link_type = "ENSEMBL_ORTHOLOGUES";

my ($conf, $compara, $from_species, @to_multi, $print, $names, $go_terms, $delete_names, $delete_go_terms);

GetOptions('conf=s'          => \$conf,
	   'compara=s'       => \$compara,
	   'from=s'          => \$from_species,
	   'to=s'            => \@to_multi,
	   'method=s'        => \$method_link_type,
	   'names'           => \$names,
	   'go_terms'        => \$go_terms,
	   'print'           => \$print,
	   'delete_names'    => \$delete_names,
	   'delete_go_terms' => \$delete_go_terms,
	   'help'            => sub { usage(); exit(0); });

@to_multi = split(/,/,join(',',@to_multi));

if (!$conf|| !$compara || !$from_species || !@to_multi) {

  usage();
  exit(1);

}

if (!$go_terms && !$names) {

  print "One or both of --names or --go_terms must be specified\n";
  print "Use --help for more detailed usage informaion\n";
  exit(1);

}

# Take values from ENSEMBL_REGISTRY environment variable or from ~/.ensembl_init
# if no reg_conf file is given.
Bio::EnsEMBL::Registry->no_version_check(1);
Bio::EnsEMBL::Registry->load_all($conf);

my $mlssa = Bio::EnsEMBL::Registry->get_adaptor($compara, 'compara', 'MethodLinkSpeciesSet');
my $ha    = Bio::EnsEMBL::Registry->get_adaptor($compara, 'compara', 'Homology');
my $ma    = Bio::EnsEMBL::Registry->get_adaptor($compara, 'compara', 'Member');

my $from_ga = Bio::EnsEMBL::Registry->get_adaptor($from_species, 'core', 'Gene');

foreach my $to_species (@to_multi) {

  my $to_ga   = Bio::EnsEMBL::Registry->get_adaptor($to_species, 'core', 'Gene');
  my $to_dbea = Bio::EnsEMBL::Registry->get_adaptor($to_species, 'core', 'DBEntry');

  backup($to_ga);

  delete_names($to_ga) if ($delete_names);
  delete_go_terms($to_ga) if ($delete_go_terms);

  my $mlss = $mlssa->fetch_by_method_link_type_registry_aliases($method_link_type, [$from_species, $to_species]);

  my $str = "gene display_xrefs and descriptions" if ($names);
  $str .= " and " if ($names && $go_terms);
  $str .= "GO terms" if ($go_terms);

  print "Projecting $str from $from_species to $to_species\n";

  # build hash of external db name -> ensembl object type mappings
  my %db_to_type = build_db_to_type($to_ga);

  print "$to_species, before projection: \n";
  print_stats($to_ga);

  # Get all genes, find homologies, set xrefs

  foreach my $gene_id (@{$from_ga->list_dbIDs}) {

    my $gene = $from_ga->fetch_by_dbID($gene_id);
    # next unless ($gene->biotype eq "protein_coding");

    my $member = $ma->fetch_by_source_stable_id("ENSEMBLGENE",$gene->stable_id);
    next unless (defined $member);

    my $homologies = $ha->fetch_all_by_Member_MethodLinkSpeciesSet($member, $mlss);

    project_homologies($homologies, $to_ga, $to_dbea, $names, $go_terms, $ma, %db_to_type);

  }

  print "$to_species, after projection: \n";
  print_stats($to_ga);

}

# ----------------------------------------------------------------------

# Project homologies from first to subsequent species
sub project_homologies() {

  my ($homologies, $to_ga, $to_dbea, $names, $go_terms, $ma, %db_to_type) = @_;

  foreach my $homology (@{$homologies}) {

    my @mas = @{$homology->get_all_Member_Attribute};
    my ($from_member, $from_attribute) = @{$mas[0]};
    my ($to_member, $to_attribute) = @{$mas[1]};

    # ----------------------------------------
    # Display names and descriptions

    project_display_names($to_ga, $to_dbea, $ma, $from_member, $to_member, %db_to_type) if ($names);

    # ----------------------------------------
    # GO terms

    project_go_terms($to_ga, $to_dbea, $ma, $from_attribute, $to_attribute) if ($go_terms);

    # ----------------------------------------

  }

}

# --------------------------------------------------------------------------------

sub project_display_names {

  my ($to_ga, $to_dbea, $ma, $from_member, $to_member, %db_to_type) = @_;

  my $to_gene = $to_ga->fetch_by_stable_id($to_member->stable_id());
  my $from_gene = $from_ga->fetch_by_stable_id($from_member->stable_id());
  my $dbEntry = $from_gene->display_xref();
  my $to_source = $to_gene->display_xref()->dbname() if ($to_gene->display_xref());
  my $from_source = $from_gene->display_xref()->dbname() if ($from_gene->display_xref());

  my $from_latin_species = Bio::EnsEMBL::Registry->get_alias($from_species);

  # if no display name set, do the projection
  if (check_overwrite_display_xref($to_gene, $from_source, $to_source)) {

    if ($dbEntry) {

      # Modify the dbEntry to indicate it's not from this species - set info_type & info_text
      my $txt = "from $from_latin_species gene " . $from_gene->stable_id();

      $dbEntry->info_type("PROJECTION");
      $dbEntry->info_text($txt);

      # Add the xref to the "to" gene, or transcript or translation depending on what the
      # other xrefs from this dbname as assigned to (see build_db_to_type)
      # Note that if type is not found, it means that we're dealing with a db that has no
      # xrefs in the target database, e.g. MarkerSymbol in mouse -> rat
      # In this case just assign to transcripts

      my @to_transcripts = @{$to_gene->get_all_Transcripts};
      my $to_transcript = $to_transcripts[0];

      my $type = $db_to_type{$dbEntry->dbname()};

      if ($type eq "Gene") {

	$to_gene->add_DBEntry($dbEntry);
	$to_dbea->store($dbEntry, $to_gene, 'Gene') if (!$print);

      } elsif ($type eq "Transcript" || !$type) {
	
	$to_transcript->add_DBEntry($dbEntry);
	$to_dbea->store($dbEntry, $to_transcript, 'Transcript') if (!$print);

      } elsif ($type eq "Translation") {

	my $to_translation = $to_transcript->translation();
	return if (!$to_translation);
	$to_translation->add_DBEntry($dbEntry);
	$to_dbea->store($dbEntry, $to_translation, 'Translation') if (!$print);

      } else {

	warn("Can't deal with xrefs assigned to $type (dbname=" . $dbEntry->dbname . ")\n");
	return;

      }

      # Set gene status to "KNOWN" and update display_xref

      $to_gene->status("KNOWN");
      #$to_gene->description($from_gene->description() . $txt) if ($from_gene->description());
      $to_gene->display_xref($dbEntry);
	
      print $to_gene->stable_id() . " --> " . $dbEntry->display_id() . "\n" if ($print);

      # update the gene so that the display_xref_id is set
      $to_ga->update($to_gene) if (!$print);

    }

  }

}

# --------------------------------------------------------------------------------

sub project_go_terms {

  my ($to_ga, $to_dbea, $ma, $from_attribute, $to_attribute) = @_;

  # GO xrefs are linked to translations, not genes<commit_msg>Set status of projected genes to "KNOWN_BY_PROJECTION" rather than KNOWN.<commit_after>use strict;

# Sets display_xref_ids for novel genes in the "to" database based
# on their orthologs in the "from" database. Can also project GO xrefs.
# Orthology relationships are read from a Compara database.

use Getopt::Long;
use Bio::EnsEMBL::Registry;
use Bio::EnsEMBL::DBSQL::DBAdaptor;
use Bio::EnsEMBL::DBSQL::GeneAdaptor;

my $method_link_type = "ENSEMBL_ORTHOLOGUES";

my ($conf, $compara, $from_species, @to_multi, $print, $names, $go_terms, $delete_names, $delete_go_terms);

GetOptions('conf=s'          => \$conf,
	   'compara=s'       => \$compara,
	   'from=s'          => \$from_species,
	   'to=s'            => \@to_multi,
	   'method=s'        => \$method_link_type,
	   'names'           => \$names,
	   'go_terms'        => \$go_terms,
	   'print'           => \$print,
	   'delete_names'    => \$delete_names,
	   'delete_go_terms' => \$delete_go_terms,
	   'help'            => sub { usage(); exit(0); });

@to_multi = split(/,/,join(',',@to_multi));

if (!$conf|| !$compara || !$from_species || !@to_multi) {

  usage();
  exit(1);

}

if (!$go_terms && !$names) {

  print "One or both of --names or --go_terms must be specified\n";
  print "Use --help for more detailed usage informaion\n";
  exit(1);

}

# Take values from ENSEMBL_REGISTRY environment variable or from ~/.ensembl_init
# if no reg_conf file is given.
Bio::EnsEMBL::Registry->no_version_check(1);
Bio::EnsEMBL::Registry->load_all($conf);

my $mlssa = Bio::EnsEMBL::Registry->get_adaptor($compara, 'compara', 'MethodLinkSpeciesSet');
my $ha    = Bio::EnsEMBL::Registry->get_adaptor($compara, 'compara', 'Homology');
my $ma    = Bio::EnsEMBL::Registry->get_adaptor($compara, 'compara', 'Member');

my $from_ga = Bio::EnsEMBL::Registry->get_adaptor($from_species, 'core', 'Gene');

foreach my $to_species (@to_multi) {

  my $to_ga   = Bio::EnsEMBL::Registry->get_adaptor($to_species, 'core', 'Gene');
  my $to_dbea = Bio::EnsEMBL::Registry->get_adaptor($to_species, 'core', 'DBEntry');

  backup($to_ga);

  delete_names($to_ga) if ($delete_names);
  delete_go_terms($to_ga) if ($delete_go_terms);

  my $mlss = $mlssa->fetch_by_method_link_type_registry_aliases($method_link_type, [$from_species, $to_species]);

  my $str = "gene display_xrefs and descriptions" if ($names);
  $str .= " and " if ($names && $go_terms);
  $str .= "GO terms" if ($go_terms);

  print "Projecting $str from $from_species to $to_species\n";

  # build hash of external db name -> ensembl object type mappings
  my %db_to_type = build_db_to_type($to_ga);

  print "$to_species, before projection: \n";
  print_stats($to_ga);

  # Get all genes, find homologies, set xrefs

  foreach my $gene_id (@{$from_ga->list_dbIDs}) {

    my $gene = $from_ga->fetch_by_dbID($gene_id);
    # next unless ($gene->biotype eq "protein_coding");

    my $member = $ma->fetch_by_source_stable_id("ENSEMBLGENE",$gene->stable_id);
    next unless (defined $member);

    my $homologies = $ha->fetch_all_by_Member_MethodLinkSpeciesSet($member, $mlss);

    project_homologies($homologies, $to_ga, $to_dbea, $names, $go_terms, $ma, %db_to_type);

  }

  print "$to_species, after projection: \n";
  print_stats($to_ga);

}

# ----------------------------------------------------------------------

# Project homologies from first to subsequent species
sub project_homologies() {

  my ($homologies, $to_ga, $to_dbea, $names, $go_terms, $ma, %db_to_type) = @_;

  foreach my $homology (@{$homologies}) {

    my @mas = @{$homology->get_all_Member_Attribute};
    my ($from_member, $from_attribute) = @{$mas[0]};
    my ($to_member, $to_attribute) = @{$mas[1]};

    # ----------------------------------------
    # Display names and descriptions

    project_display_names($to_ga, $to_dbea, $ma, $from_member, $to_member, %db_to_type) if ($names);

    # ----------------------------------------
    # GO terms

    project_go_terms($to_ga, $to_dbea, $ma, $from_attribute, $to_attribute) if ($go_terms);

    # ----------------------------------------

  }

}

# --------------------------------------------------------------------------------

sub project_display_names {

  my ($to_ga, $to_dbea, $ma, $from_member, $to_member, %db_to_type) = @_;

  my $to_gene = $to_ga->fetch_by_stable_id($to_member->stable_id());
  my $from_gene = $from_ga->fetch_by_stable_id($from_member->stable_id());
  my $dbEntry = $from_gene->display_xref();
  my $to_source = $to_gene->display_xref()->dbname() if ($to_gene->display_xref());
  my $from_source = $from_gene->display_xref()->dbname() if ($from_gene->display_xref());

  my $from_latin_species = Bio::EnsEMBL::Registry->get_alias($from_species);

  # if no display name set, do the projection
  if (check_overwrite_display_xref($to_gene, $from_source, $to_source)) {

    if ($dbEntry) {

      # Modify the dbEntry to indicate it's not from this species - set info_type & info_text
      my $txt = "from $from_latin_species gene " . $from_gene->stable_id();

      $dbEntry->info_type("PROJECTION");
      $dbEntry->info_text($txt);

      # Add the xref to the "to" gene, or transcript or translation depending on what the
      # other xrefs from this dbname as assigned to (see build_db_to_type)
      # Note that if type is not found, it means that we're dealing with a db that has no
      # xrefs in the target database, e.g. MarkerSymbol in mouse -> rat
      # In this case just assign to transcripts

      my @to_transcripts = @{$to_gene->get_all_Transcripts};
      my $to_transcript = $to_transcripts[0];

      my $type = $db_to_type{$dbEntry->dbname()};

      if ($type eq "Gene") {

	$to_gene->add_DBEntry($dbEntry);
	$to_dbea->store($dbEntry, $to_gene, 'Gene') if (!$print);

      } elsif ($type eq "Transcript" || !$type) {
	
	$to_transcript->add_DBEntry($dbEntry);
	$to_dbea->store($dbEntry, $to_transcript, 'Transcript') if (!$print);

      } elsif ($type eq "Translation") {

	my $to_translation = $to_transcript->translation();
	return if (!$to_translation);
	$to_translation->add_DBEntry($dbEntry);
	$to_dbea->store($dbEntry, $to_translation, 'Translation') if (!$print);

      } else {

	warn("Can't deal with xrefs assigned to $type (dbname=" . $dbEntry->dbname . ")\n");
	return;

      }

      # Set gene status to "KNOWN_BY_PROJECTION" and update display_xref
      # also set the status of the gene's transcripts
      $to_gene->status("KNOWN_BY_PROJECTION");
      $to_gene->display_xref($dbEntry);
      foreach my $transcript (@{$to_gene->get_all_Transcripts()}) {
	$transcript->status("KNOWN_BY_PROJECTION");
      }
	
      print $to_gene->stable_id() . " --> " . $dbEntry->display_id() . "\n" if ($print);

      # update the gene so that the display_xref_id is set
      $to_ga->update($to_gene) if (!$print);

    }

  }

}

# --------------------------------------------------------------------------------

sub project_go_terms {

  my ($to_ga, $to_dbea, $ma, $from_attribute, $to_attribute) = @_;

  # GO xrefs are linked to translations, not genes
{'fraction_non_alphanumeric': 0.20145891439605235, 'fraction_numerical': 0.0010012157619967103, 'mean_word_length': 3.2375757575757578, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 128, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6609500', 'n_tokens_mistral': 5135, 'n_tokens_neox': 4779, 'n_words': 1105}