<commit_before>package org.bbop.apollo

import org.bbop.apollo.gwt.shared.FeatureStringEnum

import grails.transaction.Transactional
import org.apache.commons.lang.RandomStringUtils
import org.bbop.apollo.sequence.SequenceTranslationHandler
import org.bbop.apollo.sequence.StandardTranslationTable
import org.bbop.apollo.sequence.Strand
import org.codehaus.groovy.grails.web.json.JSONArray
import org.codehaus.groovy.grails.web.json.JSONException
import org.codehaus.groovy.grails.web.json.JSONObject

import java.util.zip.CRC32

@Transactional
class SequenceService {
    
    def configWrapperService
    def grailsApplication
    def featureService
    def transcriptService
    def exonService
    def cdsService
    def gff3HandlerService
    def overlapperService

    List<FeatureLocation> getFeatureLocations(Sequence sequence){
        FeatureLocation.findAllBySequence(sequence)
    }

    /**
     * Get residues from sequence . . . could be multiple locations
     * @param feature
     * @return
     */
    String getResiduesFromFeature(Feature feature ) {
        List<FeatureLocation> featureLocationList = FeatureLocation.createCriteria().list {
            eq("feature",feature)
            order("fmin","asc")
        }
        String returnResidue = ""

        for(FeatureLocation featureLocation in featureLocationList){
            returnResidue += getResidueFromFeatureLocation(featureLocation)
        }
        
        if(featureLocationList.first().strand==Strand.NEGATIVE.value){
            returnResidue = SequenceTranslationHandler.reverseComplementSequence(returnResidue)
        }

        return returnResidue
    }

    String getResidueFromFeatureLocation(FeatureLocation featureLocation) {
        return getRawResiduesFromSequence(featureLocation.sequence,featureLocation.fmin,featureLocation.fmax)
    }


    String getGenomicResiduesFromSequenceWithAlterations(FlankingRegion flankingRegion) {
        return getGenomicResiduesFromSequenceWithAlterations(flankingRegion.sequence,flankingRegion.fmin,flankingRegion.fmax,flankingRegion.strand)
    }

    /**
     * Just meant for non-transcript genomic sequence
     * @param sequence
     * @param fmin
     * @param fmax
     * @param strand
     * @return
     */
    String getGenomicResiduesFromSequenceWithAlterations(Sequence sequence, int fmin, int fmax,Strand strand) {
        String residueString = getRawResiduesFromSequence(sequence,fmin,fmax)
        if(strand==Strand.NEGATIVE){
            residueString = SequenceTranslationHandler.reverseComplementSequence(residueString)
        }

        StringBuilder residues = new StringBuilder(residueString);
        List<SequenceAlteration> sequenceAlterationList = SequenceAlteration.executeQuery("select distinct sa from SequenceAlteration sa join sa.featureLocations fl join fl.sequence seq where seq.id = :seqId ",[seqId:sequence.id])
        int currentOffset = 0;
        // TODO: refactor with getResidues in FeatureService so we are calling a similar method
        for(SequenceAlteration sequenceAlteration in sequenceAlterationList){
            int localCoordinate = featureService.convertSourceCoordinateToLocalCoordinate(fmin,fmax,strand, sequenceAlteration.featureLocation.fmin);
            if(!overlapperService.overlaps(fmin,fmax,sequenceAlteration.featureLocation.fmin,sequenceAlteration.featureLocation.fmax)){
                continue
            }

            // TODO: is this correct?
            String sequenceAlterationResidues = sequenceAlteration.alterationResidue
            if (strand == Strand.NEGATIVE) {
                sequenceAlterationResidues = SequenceTranslationHandler.reverseComplementSequence(sequenceAlterationResidues);
            }
            // Insertions
            if (sequenceAlteration instanceof Insertion) {
                if (strand==Strand.NEGATIVE) {<commit_msg>fixed to make integration test more consistent<commit_after>package org.bbop.apollo

import org.bbop.apollo.gwt.shared.FeatureStringEnum

import grails.transaction.Transactional
import org.apache.commons.lang.RandomStringUtils
import org.bbop.apollo.sequence.SequenceTranslationHandler
import org.bbop.apollo.sequence.StandardTranslationTable
import org.bbop.apollo.sequence.Strand
import org.codehaus.groovy.grails.web.json.JSONArray
import org.codehaus.groovy.grails.web.json.JSONException
import org.codehaus.groovy.grails.web.json.JSONObject

import java.util.zip.CRC32

@Transactional
class SequenceService {
    
    def configWrapperService
    def grailsApplication
    def featureService
    def transcriptService
    def exonService
    def cdsService
    def gff3HandlerService
    def overlapperService

    List<FeatureLocation> getFeatureLocations(Sequence sequence){
        FeatureLocation.findAllBySequence(sequence)
    }

    /**
     * Get residues from sequence . . . could be multiple locations
     * @param feature
     * @return
     */
    String getResiduesFromFeature(Feature feature ) {
        List<FeatureLocation> featureLocationList = FeatureLocation.createCriteria().list {
            eq("feature",feature)
            order("fmin","asc")
        }
        String returnResidue = ""

        for(FeatureLocation featureLocation in featureLocationList){
            returnResidue += getResidueFromFeatureLocation(featureLocation)
        }
        
        if(featureLocationList.first().strand==Strand.NEGATIVE.value){
            returnResidue = SequenceTranslationHandler.reverseComplementSequence(returnResidue)
        }

        return returnResidue
    }

    String getResidueFromFeatureLocation(FeatureLocation featureLocation) {
        return getRawResiduesFromSequence(featureLocation.sequence,featureLocation.fmin,featureLocation.fmax)
    }


    String getGenomicResiduesFromSequenceWithAlterations(FlankingRegion flankingRegion) {
        return getGenomicResiduesFromSequenceWithAlterations(flankingRegion.sequence,flankingRegion.fmin,flankingRegion.fmax,flankingRegion.strand)
    }

    /**
     * Just meant for non-transcript genomic sequence
     * @param sequence
     * @param fmin
     * @param fmax
     * @param strand
     * @return
     */
    String getGenomicResiduesFromSequenceWithAlterations(Sequence sequence, int fmin, int fmax,Strand strand) {
        String residueString = getRawResiduesFromSequence(sequence,fmin,fmax)
        if(strand==Strand.NEGATIVE){
            residueString = SequenceTranslationHandler.reverseComplementSequence(residueString)
        }

        StringBuilder residues = new StringBuilder(residueString);
        List<SequenceAlteration> sequenceAlterationList = SequenceAlteration.executeQuery("select distinct sa from SequenceAlteration sa join sa.featureLocations fl join fl.sequence seq where seq.id = :seqId ",[seqId:sequence.id])
        int currentOffset = 0;
        // TODO: refactor with getResidues in FeatureService so we are calling a similar method
        for(SequenceAlteration sequenceAlteration in sequenceAlterationList.sort(){ a,b ->
                 a.featureLocation.fmin <=> b.featureLocation.fmin
        }){
            int localCoordinate = featureService.convertSourceCoordinateToLocalCoordinate(fmin,fmax,strand, sequenceAlteration.featureLocation.fmin);
            if(!overlapperService.overlaps(fmin,fmax,sequenceAlteration.featureLocation.fmin,sequenceAlteration.featureLocation.fmax)){
                continue
            }

            // TODO: is this correct?
            String sequenceAlterationResidues = sequenceAlteration.alterationResidue
            if (strand == Strand.NEGATIVE) {
                sequenceAlterationResidues = SequenceTranslationHandler.reverseComplementSequence(sequenceAlterationResidues);
            }
            // Insertions
            if (sequenceAlteration instanceof Insertion) {
                if (strand==Strand.NEGATIVE) {
{'fraction_non_alphanumeric': 0.07102020073688223, 'fraction_numerical': 0.0010163892770931266, 'mean_word_length': 3.477815699658703, 'pattern_counts': {'":': 0, '<': 10, '<?xml version=': 0, '>': 11, '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': '2401193', 'n_tokens_mistral': 2159, 'n_tokens_neox': 2054, 'n_words': 375}