<commit_before>
# Module containing methods for checking LRG XML files prior to release

use strict;
use warnings;
use LRG::LRG;
use POSIX qw(getcwd);
use List::Util qw(min max);
use Bio::Seq;

package LRGHealthcheck;

# The java executable (needed for validation of the schema).
our $JAVA = 'java';
# Path to the jing jar file. Assume it's in cwd by default 
our $JING_JAR = POSIX::getcwd() . '/jing.jar'; 
#Path to the RelaxNG Compact XML schema definition file
our $RNC_FILE = POSIX::getcwd() . '/LRG.rnc'; 

# The available checks
our @CHECKS = (
    'schema',
    'id',
    'cDNA',
    'translation',
    'exons',
    'phases',
    'exon_labels',
    'mappings',
    'gene_name',
    'partial'
);

# Constructor
sub new {
    my $xml_file = shift;
    
    my $hc;
    
    # Check that we got an xml file, die otherwise
    die("An XML file is required") unless (defined($xml_file));
    # Check that the supplied xml file exists, die otherwise
    die("Supplied XML file $xml_file does not exist") unless (-e $xml_file);
    
    # Get a LRG object from the XML file
    my $lrg = LRG::LRG::newFromFile($xml_file) or die("Could not create LRG object from XML file $xml_file");
    
    $hc->{'xml_file'} = $xml_file;
    $hc->{'lrg'} = $lrg;
    
    #Set the LRG id to the content of the id tag
    $hc->{'lrg_id'} = $lrg->findNode("fixed_annotation/id")->content();
    
    # The healthcheck has a hash that holds the results of the different checks
    foreach my $check (@CHECKS) {
        $hc->{'check'}{$check} = {};
    }
    
    # Bless and return
    bless $hc, 'LRGHealthcheck';
    return $hc;
}

# Check that the cDNA constructed from genomic sequence and exon coordinates is identical to the cDNA specified within the record
sub cDNA {
    my $self = shift;
    
    my $passed;
    
    # Name of this check
    my $name = sub_name();
    
    #Get the genomic sequence from the XML record
    my $genomic_seq = $self->get_genomic_sequence($name);
    
    # Check that the sequence exists. If not, return from the test
    return 0 if (!defined($genomic_seq));
    
    #Get the transcripts
    my $transcripts = $self->get_transcripts($name);
    return 0 if (!defined($transcripts));
    
    $passed = 1;
    
    # Check each transcript
    foreach my $transcript (@{$transcripts}) {
        # Get the name
        my $tr_name = $transcript->data()->{'name'};
        
        #Get the supplied cDNA sequence
        my $tr_cdna = $transcript->findNode('cdna/sequence')->content();
        if (!defined($tr_cdna) || length($tr_cdna) == 0) {
            $passed = 0;
            $self->{'check'}{$name}{'message'} .= "Could not find a supplied cDNA sequence for transcript $tr_name in XML file//";
        }
        
        #Get the genomic features
        my $features = $self->get_genomic_features($name,$transcript,$genomic_seq);
        my $genomic_cdna = $features->{'cdna'};
        
        # Compare the cDNAs
        if ($genomic_cdna ne $tr_cdna) {
            $passed = 0;
            $self->{'check'}{$name}{'message'} .= "Transcript $tr_name cDNA sequence defined by genomic sequence and exon coordinates is different from cDNA sequence supplied in XML file//";
            $self->{'check'}{$name}{'message'} .= "Genomic:\t$genomic_cdna//";
            $self->{'check'}{$name}{'message'} .= "Supplied:\t$tr_cdna//";
        }
    }
    
    $self->{'check'}{$name}{'passed'} = $passed;
    return $passed;
}
<commit_msg>Added healthcheck for start and end coordinates<commit_after># Module containing methods for checking LRG XML files prior to release

use strict;
use warnings;
use LRG::LRG;
use POSIX qw(getcwd);
use List::Util qw(min max);
use Bio::Seq;

package LRGHealthcheck;

# The java executable (needed for validation of the schema).
our $JAVA = 'java';
# Path to the jing jar file. Assume it's in cwd by default 
our $JING_JAR = POSIX::getcwd() . '/jing.jar'; 
#Path to the RelaxNG Compact XML schema definition file
our $RNC_FILE = POSIX::getcwd() . '/LRG.rnc'; 

# The available checks
our @CHECKS = (
    'schema',
    'id',
    'cDNA',
    'translation',
    'exons',
    'phases',
    'exon_labels',
    'mappings',
    'gene_name',
    'partial',
    'coordinates'
);

# Constructor
sub new {
    my $xml_file = shift;
    
    my $hc;
    
    # Check that we got an xml file, die otherwise
    die("An XML file is required") unless (defined($xml_file));
    # Check that the supplied xml file exists, die otherwise
    die("Supplied XML file $xml_file does not exist") unless (-e $xml_file);
    
    # Get a LRG object from the XML file
    my $lrg = LRG::LRG::newFromFile($xml_file) or die("Could not create LRG object from XML file $xml_file");
    
    $hc->{'xml_file'} = $xml_file;
    $hc->{'lrg'} = $lrg;
    
    #Set the LRG id to the content of the id tag
    $hc->{'lrg_id'} = $lrg->findNode("fixed_annotation/id")->content();
    
    # The healthcheck has a hash that holds the results of the different checks
    foreach my $check (@CHECKS) {
        $hc->{'check'}{$check} = {};
    }
    
    # Bless and return
    bless $hc, 'LRGHealthcheck';
    return $hc;
}

# Check that the cDNA constructed from genomic sequence and exon coordinates is identical to the cDNA specified within the record
sub cDNA {
    my $self = shift;
    
    my $passed;
    
    # Name of this check
    my $name = sub_name();
    
    #Get the genomic sequence from the XML record
    my $genomic_seq = $self->get_genomic_sequence($name);
    
    # Check that the sequence exists. If not, return from the test
    return 0 if (!defined($genomic_seq));
    
    #Get the transcripts
    my $transcripts = $self->get_transcripts($name);
    return 0 if (!defined($transcripts));
    
    $passed = 1;
    
    # Check each transcript
    foreach my $transcript (@{$transcripts}) {
        # Get the name
        my $tr_name = $transcript->data()->{'name'};
        
        #Get the supplied cDNA sequence
        my $tr_cdna = $transcript->findNode('cdna/sequence')->content();
        if (!defined($tr_cdna) || length($tr_cdna) == 0) {
            $passed = 0;
            $self->{'check'}{$name}{'message'} .= "Could not find a supplied cDNA sequence for transcript $tr_name in XML file//";
        }
        
        #Get the genomic features
        my $features = $self->get_genomic_features($name,$transcript,$genomic_seq);
        my $genomic_cdna = $features->{'cdna'};
        
        # Compare the cDNAs
        if ($genomic_cdna ne $tr_cdna) {
            $passed = 0;
            $self->{'check'}{$name}{'message'} .= "Transcript $tr_name cDNA sequence defined by genomic sequence and exon coordinates is different from cDNA sequence supplied in XML file//";
            $self->{'check'}{$name}{'message'} .= "Genomic:\t$genomic_cdna//";
            $self->{'check'}{$name}{'message'} .= "Supplied:\t$tr_cdna//";
        }
    }
    
    $self->{'check'}{$name}{'passed'} = $passed;
    return $passed;
}

# Check that all coordinates are specified with start less than end
sub coordinates {
    my $self = shift;
    
    my $passed = 1;
    
    # Name of this check
    my $name = sub_name();
    
    #Get all elements in the LRG XML
    my $nodes = $self->{'lrg'}->getAllNodes();
    
    #Loop over all nodes and check the data attributes for coordinates
    my $prefix;
    foreach my $node (@{$nodes}) {
        my $data = $node->data() or next;
        foreach my $key (keys(%{$data})) {
            if ($key =~ m/^(.*\_?)start$/) {
                $prefix = $1;
                if (exists($data->{$prefix . 'end'}) && $data->{$key} > $data->{$prefix . 'end'}) {
                    $passed = 0;
                    $self->{'check'}{$name}{'message'} .= $prefix . "start coordinate is greater than " . $prefix . "end coordinate in " . $node->name() . " tag//";
                }
            }
        }
    }
    
    $self->{'check'}{$name}{'passed'} = $passed;
    return $passed;
}
  
{'fraction_non_alphanumeric': 0.1402033387724363, 'fraction_numerical': 0.0018827664114472197, 'mean_word_length': 2.58273381294964, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 20}, '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': '1671085', 'n_tokens_mistral': 2620, 'n_tokens_neox': 2494, 'n_words': 805}