/*
 * The Gemma project.
 * 
 * Copyright (c) 2006 University of British Columbia
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 */
package ubic.gemma.model.genome.sequenceAnalysis;

import org.apache.commons.lang.StringUtils;

/**
 * @author pavlidis
 * @version $Id$
 * @see ubic.gemma.model.sequence.sequenceAnalysis.BlatResult
 */
public class BlatResultImpl extends ubic.gemma.model.genome.sequenceAnalysis.BlatResult {

    /**
     * 
     */
    private static final long serialVersionUID = -8157023595754885730L;

    /**
     * Based on the JKSrc method in psl.c. However, we do not double-penalize for mismatches (they are not subtracted
     * from the matches). The gap penalties are implemented as in psl.c.
     * 
     * @return Value between 0 and 1, representing the fraction of matches, minus a gap penalty.
     * @see ubic.gemma.model.sequence.sequenceAnalysis.BlatResult#score()
     */
    @Override
    public Double score() {
        long length;
        if ( this.getQuerySequence() == null ) {
            throw new IllegalArgumentException( "Sequence cannot be null" );
        }
        if ( this.getQuerySequence().getLength() != null && this.getQuerySequence().getLength() != 0 ) {
            if ( StringUtils.isNotBlank( this.getQuerySequence().getSequence() ) ) {
                length = this.getQuerySequence().getSequence().length();
            } else {
                throw new IllegalArgumentException( "No sequence length information for " + this.getQuerySequence() );
            }
        } else {
            length = this.getQuerySequence().getLength();
        }
        assert length > 0;
        return ( ( double ) this.getMatches() - ( double ) this.getQueryGapCount() - this.getTargetGapCount() )
                / length;
    }

    /**
     * Fraction identity computation, as in psl.c.
     * 
     * @return Value between 0 and 1.
     * @see http://genome.ucsc.edu/FAQ/FAQblat#blat4
     */
    @Override
    public Double identity() {
        int sizeMul = 1; // assuming DNA; use 3 for protein.
        long qAliSize = sizeMul * this.getQueryEnd() - this.getQueryStart();
        long tAliSize = this.getTargetEnd() - this.getTargetStart();
        long aliSize = Math.min( qAliSize, tAliSize );

        if ( aliSize <= 0 ) return 0.0;

        long sizeDif = qAliSize - tAliSize;
        if ( sizeDif < 0 ) {
            sizeDif = 0; // here assuming "isMrna" is true. ("The parameter isMrna should be set to TRUE, regardless
            // of whether the input sequence is mRNA or protein")
        }
        int insertFactor = this.getQueryGapCount() + this.getTargetGapCount(); // assuming isMRNA is true.
        int total = ( sizeMul * ( this.getMatches() + this.getRepMatches() + this.getMismatches() ) );
        int milliBad = 0;
        if ( total != 0 ) {
            milliBad = ( 1000 * ( this.getMismatches() * sizeMul + insertFactor + ( int ) Math.round( 3.0 * Math
                    .log( 1.0 + sizeDif ) ) ) )
                    / total;
        }
        assert milliBad >= 0 && milliBad <= 1000 : "Millibad was ourside of range 0-1000: " + milliBad;
        return 100.0 - milliBad * 0.1;
    }
}
@@ -1770,32 +1770,33 @@
 l%22 );%0A        %7D%0A
+%0A
         if ( thi
@@ -1876,32 +1876,107 @@
 ngth() != 0 ) %7B%0A
+            length = this.getQuerySequence().getLength();%0A        %7D else %7B%0A
             if (
@@ -2284,83 +2284,9 @@
    %7D
- else %7B%0A            length = this.getQuerySequence().getLength();%0A        %7D
+%0A
 %0A   

fix broken logic in score()