/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package javaapplication1;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;

/**
 *
 * @author legrand
 */
public class Bscore {

    ReadAlignement alignement;
    String fileDichletMixture;
    ArrayList catalytique;
    int catalytiquen = 0;
    ArrayList<ArrayList<Double>> resultats;

    public Bscore(ReadAlignement alignement, String fileDichletMixture) {
        this.alignement = alignement;
        this.fileDichletMixture = fileDichletMixture;
        resultats = new ArrayList();

    }

    public Bscore(ReadAlignement alignement, String fileDichletMixture, ArrayList catalytique) {
        this.alignement = alignement;
        this.fileDichletMixture = fileDichletMixture;
        this.catalytique = catalytique;
        resultats = new ArrayList();

    }

    /**
     * log base 2
     *
     * @param d
     * @return log base 2(d)*
     */
    public static double log2(double d) {
        return Math.log(d) / Math.log(2.0);
    }

    /**
     * Calcul le log 2 de a puissance b
     *
     * @param a
     * @param b
     * @return
     */
    public double log2puissance(double a, double b) {
        //si la puissance est faible on calcule 
        if (b < 30) {
            return log2(Math.pow(a, b));
            // si non on fait une approximation
        } else {
            return b / Math.log(2.0);
        }

    }

    /**
     * Renvois une colonne de l'allignement
     *
     * @param number
     * @return colonne numero number de l'allignement
     */
    ArrayList column(int number) {
        ArrayList column = new ArrayList();
        for (int i = 0; i < alignement.sequenceArray.size(); i++) {
            Sequence sequence = (Sequence) alignement.sequenceArray.get(i);
            column.add(sequence.Seq.get(number));

        }
        return column;
    }

    /**
     * calcule le score de la colonne
     *
     * @param number
     * @return score de la colonne
     */
    double scorecolonne(int number) {
        DirichletMixture dirichletMixture = new DirichletMixture(fileDichletMixture);
        ArrayList column = column(number);
        //on initialise le score(a 1 car on multiplie)
        double columnscoreRelatedness = 1;
        //on fait la somme multiplicative de la probabilité de chaque acide aminé
        for (int naa = 0; naa < column.size(); naa++) {
            double a = dirichletMixture.Prob((String) column.get(naa));
            columnscoreRelatedness *= a;

        }
        int numberofAminoAcid = (dirichletMixture.ArrayOfDirichlet.get(0)).ArrayOfResidu.length;
  
        double logcolumnscoreNonRelatedness = log2puissance(numberofAminoAcid, column.size());
        double columnscore = log2(columnscoreRelatedness) + logcolumnscoreNonRelatedness;

        //on divise par le nombre de residus dans la  colonnes:
        columnscore /= column.size();
        if (columnscore < -2) {
            columnscore = -2;
        }
    
       

        return columnscore;
    }

    /**
     * score normaliser pas utiliser
     *
     * @param scoreAlignement
     * @return score de chaque collones- moyenne des scores/variance
     */
    /*
    ArrayList normalizeColumnScore(ArrayList scoreAlignement) {
        //calcul de la somme
        double scoreAlignementSum = 0;
        for (int c = 0; c < scoreAlignement.size(); c++) {
            scoreAlignementSum += (Double) scoreAlignement.get(c);
        }
        double moyenne = scoreAlignementSum / scoreAlignement.size();
        //calcul de la variance
        double variance = 0;
        for (int c = 0; c < scoreAlignement.size(); c++) {
            double scorea = (Double) scoreAlignement.get(c);
            variance += (scorea - moyenne) * (scorea - moyenne);
        }
        variance = Math.sqrt(variance);
        // on divise chaque score par la somme
        for (int c = 0; c < scoreAlignement.size(); c++) {
            double sc = (Double) scoreAlignement.get(c);
            scoreAlignement.set(c, (sc - moyenne) / variance);
        }
        return scoreAlignement;
    }
    */

    /**
     * calcul le Bscore de chaque collonne de l'allignement en faisant appel à
     * scorecolonne()
     *
     * @return Bscore de chaque collonne de l'allignement
     */
    ArrayList<Double> scoreAlignement() {
        ArrayList<Double> scoreAlignement = new ArrayList();
        int sizesequence = (((alignement.sequenceArray).get(1)).Seq).size();
        for (int c = 0; c < sizesequence; c++) {
            scoreAlignement.add(scorecolonne(c));
        }
        //normalizeColumnScore(scoreAlignement);
        return scoreAlignement;
    }

    /**
     *****
     * calcule faux positif precision,sensitivié...
     */
    ArrayList scoregarder() {
        //0.001 pour eviter division par 0
        double truePositif = 0.001;
        double falsePositif = 0.001;
        double falseNegatif = 0.001;
        double trueNegatif = 0.001;
        ArrayList<ArrayList<Double>> resultatsOrderer = new ArrayList();
        /*resultatsOrderer.add(resultats.get(0));
         int numberofresidutokeep=resultats.size()/100;
         for (int y=1;y<resultats.size();y++){
         for (int i=0;i<resultatsOrderer.size();i++){
         double a=(double)resultats.get(y).get(1);
         double b=(double)resultatsOrderer.get(i).get(1);
         if (a> b){
         resultatsOrderer.add(i,resultats.get(y));
         break;
         }
         if (i==resultatsOrderer.size()){
         resultatsOrderer.add(resultats.get(y));
         }
         }
         }

         for(int i=0;i<resultatsOrderer.size();i++){
         if(i<=numberofresidutokeep){
         double a=1;
         if(resultatsOrderer.get(i).get(0).equals(a)){
         truePositif+=1;
         }else{
         falsePositif+=1;
         }
         }
         else{
         if(resultatsOrderer.get(i).get(0)==1){
         falseNegatif+=1;
         }else{
         trueNegatif+=1;
         }
         }
         }*/

        ///teste avec un score:
        double valeur = 0.6;
        for (int i = 0; i < resultats.size(); i++) {
            if (resultats.get(i).get(0) == 1) {
                if (resultats.get(i).get(1) > valeur) {
                    truePositif += 1;
                } else {
                    falsePositif += 1;
                }

            } else {
                if (resultats.get(i).get(1) > valeur) {
                    falseNegatif += 1;
                } else {
                    trueNegatif += 1;
                }

            }
        }
        System.out.println(truePositif + " " + trueNegatif + " " + falsePositif + " " + falseNegatif);
        double precision = truePositif / (truePositif + falsePositif);
        double recal = truePositif / (truePositif + falseNegatif);
        double specificity = falsePositif / (falsePositif + trueNegatif);

         //cas ou on a diviser par 0
        //if(specificity!=specificity){specificity=1;};
        System.out.println("precision=" + precision);
        System.out.println("sensitivité=" + recal);
        System.out.println("Specificité=" + specificity);
        ArrayList n = new ArrayList();
        n.add(precision);
        n.add(recal);
        n.add(specificity);
        System.out.println(n.toString());

        return n;

    }

    /**
     * cree ficher de score separer par des | pour jalaview
     *
     * @param scoreAlignement//score des alignments
     * @param name //nom du fichier a sauvegarder
     */
    void jalaview(ArrayList<Double> scoreAlignement, String name) {
        String s = "JALVIEW_ANNOTATION" + "\n" + "BAR_GRAPH	BILD	";
        for (int score = 0; score < scoreAlignement.size(); score++) {
            if (score != (scoreAlignement.size() - 1)) {
                s += (2 + scoreAlignement.get(score)) + "|";
            } else {
                s += scoreAlignement.get(score);
            }
        }
        s += "\n" + "COLOUR	BILD	555555";

        try {
            File file = new File("/home/legrand/Documents/jalaview/" + name + ".bg");

            // if file doesnt exists, then create it
            if (!file.exists()) {
                file.createNewFile();
            }

            FileWriter fw = new FileWriter(file.getAbsoluteFile());
            BufferedWriter bw = new BufferedWriter(fw);
            bw.write(s);
            bw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * moyenne de score pour toute les fenetres d'une certaine taille
     *
     * @param scoreAlignement
     * @param sizeWindows renvois une arraylist avec le score pour chaque
     * fenetres
     */
    ArrayList scorewindows(ArrayList scoreAlignement, int sizeWindows) {
        ArrayList scorewindows = new ArrayList();
        for (int score = 0; score < scoreAlignement.size() - sizeWindows; score++) {
            double sumscore = 0;
            for (int i = score; i < sizeWindows + score; i++) {
                sumscore += (Double) scoreAlignement.get(i);
            }
            sumscore /= sizeWindows;
            scorewindows.add(sumscore);
        }
        return scorewindows;
    }
}
