/********* JTT MODEL OF PROTEIN EVOLUTION ************/
LoadFunctionLibrary("../empirical.bf");
LoadFunctionLibrary("../../protein.bf");
LoadFunctionLibrary("../../parameters.bf");
LoadFunctionLibrary("../../frequencies.bf");
LoadFunctionLibrary("../../../UtilityFunctions.bf");
LoadFunctionLibrary("../../../all-terms.bf");



/**
 * @name models.protein.JTT.ModelDescription
 * @description Create the baseline schema (dictionary) for the JTT model of protein evolution
 * @returns {Dictionary} model description
 * @param {String} type
 */
function models.protein.JTT.ModelDescription(type) {
    models.protein.JTT.ModelDescription.model_definition = models.protein.empirical.ModelDescription(type);
    models.protein.JTT.ModelDescription.model_definition [terms.model.empirical_rates] = models.protein.JTT.Rij;
    models.protein.JTT.ModelDescription.model_definition [terms.model.frequency_estimator] = "models.protein.JTT.frequencies";
    return models.protein.JTT.ModelDescription.model_definition;
}

/**
 * @name models.protein.JTTF.ModelDescription
 * @description Create the baseline schema (dictionary) for the JTT+F model of protein evolution
 * @returns {Dictionary} model description
 * @param {String} type
 */
function models.protein.JTTF.ModelDescription(type) {
    models.protein.JTTF.ModelDescription.model_definition = models.protein.JTT.ModelDescription(type);
    models.protein.JTTF.ModelDescription.model_definition [terms.model.frequency_estimator] = "frequencies.empirical.protein";
    models.protein.JTTF.ModelDescription.model_definition [terms.model.efv_estimate_name] = utility.getGlobalValue("terms.frequencies._20x1");
    return models.protein.JTTF.ModelDescription.model_definition;
}

/**
 * @name models.protein.JTTML.ModelDescription
 * @description Create the baseline schema (dictionary) for the JTT+ML model of protein evolution
 * @returns {Dictionary} model description
 * @param {String} type
 */
function models.protein.JTTML.ModelDescription(type) {
    models.protein.JTTML.ModelDescription.model_definition = models.protein.JTT.ModelDescription(type);
    models.protein.JTTML.ModelDescription.model_definition [terms.model.frequency_estimator] = "frequencies.ML.protein";
    models.protein.JTTML.ModelDescription.model_definition [terms.model.efv_estimate_name]   =  utility.getGlobalValue("terms.frequencies.MLE");
    return models.protein.JTTML.ModelDescription.model_definition;
}

/* Define a dictionary of amino-acid exchangeability rates for the JTT model of protein evolution. */ 
models.protein.JTT.Rij = {
'A': {'C': 0.56,
       'D': 0.81,
       'E': 1.05,
       'F': 0.15,
       'G': 1.79,
       'H': 0.27,
       'I': 0.36,
       'K': 0.35,
       'L': 0.30,
       'M': 0.54,
       'N': 0.54,
       'P': 1.94,
       'Q': 0.57,
       'R': 0.58,
       'S': 3.78,
       'T': 4.75,
       'V': 2.98,
       'W': 0.09,
       'Y': 0.11},
 'C': {'D': 0.10,
       'E': 0.05,
       'F': 0.78,
       'G': 0.59,
       'H': 0.69,
       'I': 0.17,
       'K': 0.07,
       'L': 0.23,
       'M': 0.31,
       'N': 0.34,
       'P': 0.14,
       'Q': 0.09,
       'R': 1.13,
       'S': 2.23,
       'T': 0.42,
       'V': 0.62,
       'W': 1.15,
       'Y': 2.09},
 'D': {'E': 7.67,
       'F': 0.04,
       'G': 1.30,
       'H': 1.12,
       'I': 0.11,
       'K': 0.26,
       'L': 0.07,
       'M': 0.15,
       'N': 5.28,
       'P': 0.15,
       'Q': 0.49,
       'R': 0.16,
       'S': 0.59,
       'T': 0.38,
       'V': 0.31,
       'W': 0.04,
       'Y': 0.46},
 'E': {'F': 0.05,
       'G': 1.19,
       'H': 0.26,
       'I': 0.12,
       'K': 1.81,
       'L': 0.09,
       'M': 0.18,
       'N': 0.58,
       'P': 0.18,
       'Q': 3.23,
       'R': 0.29,
       'S': 0.30,
       'T': 0.32,
       'V': 0.45,
       'W': 0.10,
       'Y': 0.07},
 'F': {'G': 0.05,
       'H': 0.40,
       'I': 0.89,
       'K': 0.04,
       'L': 2.48,
       'M': 0.43,
       'N': 0.10,
       'P': 0.17,
       'Q': 0.04,
       'R': 0.05,
       'S': 0.92,
       'T': 0.12,
       'V': 0.62,
       'W': 0.53,
       'Y': 5.36},
 'G': {'H': 0.23,
       'I': 0.06,
       'K': 0.27,
       'L': 0.06,
       'M': 0.14,
       'N': 0.81,
       'P': 0.24,
       'Q': 0.26,
       'R': 1.37,
       'S': 2.01,
       'T': 0.33,
       'V': 0.47,
       'W': 0.55,
       'Y': 0.08},
 'H': {'I': 0.16,
       'K': 0.45,
       'L': 0.56,
       'M': 0.33,
       'N': 3.91,
       'P': 1.15,
       'Q': 5.97,
       'R': 3.28,
       'S': 0.73,
       'T': 0.46,
       'V': 0.11,
       'W': 0.08,
       'Y': 5.73},
 'I': {'K': 0.21,
       'L': 2.29,
       'M': 4.79,
       'N': 0.47,
       'P': 0.10,
       'Q': 0.09,
       'R': 0.22,
       'S': 0.40,
       'T': 2.45,
       'V': 9.61,
       'W': 0.09,
       'Y': 0.32},
 'K': {'L': 0.14,
       'M': 0.65,
       'N': 2.63,
       'P': 0.21,
       'Q': 2.92,
       'R': 6.46,
       'S': 0.47,
       'T': 1.03,
       'V': 0.14,
       'W': 0.10,
       'Y': 0.08},
 'L': {'M': 3.88,
       'N': 0.12,
       'P': 1.02,
       'Q': 0.72,
       'R': 0.38,
       'S': 0.59,
       'T': 0.25,
       'V': 1.80,
       'W': 0.52,
       'Y': 0.24},
 'M': {'N': 0.30,
       'P': 0.16,
       'Q': 0.43,
       'R': 0.44,
       'S': 0.29,
       'T': 2.26,
       'V': 3.23,
       'W': 0.24,
       'Y': 0.18},
 'N': {'P': 0.15,
       'Q': 0.86,
       'R': 0.45,
       'S': 5.03,
       'T': 2.32,
       'V': 0.16,
       'W': 0.08,
       'Y': 0.70},
 'P': {'Q': 1.64,
       'R': 0.74,
       'S': 2.85,
       'T': 1.18,
       'V': 0.23,
       'W': 0.06,
       'Y': 0.10},
 'Q': {'R': 3.10,
       'S': 0.53,
       'T': 0.51,
       'V': 0.20,
       'W': 0.18,
       'Y': 0.24},
 'R': {'S': 1.01, 'T': 0.64, 'V': 0.17, 'W': 1.26, 'Y': 0.20},
 'S': {'T': 4.77, 'V': 0.38, 'W': 0.35, 'Y': 0.63},
 'T': {'V': 1.12, 'W': 0.12, 'Y': 0.21},
 'V': {'W': 0.25, 'Y': 0.16},
 'W': {'Y': 0.71},
 'Y': {}};


/**
 * @name models.protein.JTT.frequencies
 * @param {Dictionary} Baseline JTT model
 * @returns {Dictionary} Updated JTT model with empirical frequencies
 * @description Define the empirical amino acid frequencies associated with the JTT model of protein evolution
 */
lfunction models.protein.JTT.frequencies (model, namespace, datafilter) {
    model[utility.getGlobalValue("terms.efv_estimate")] =
        {{0.076748}
        {0.019803}
        {0.051544}
        {0.061830}
        {0.040126}
        {0.073152}
        {0.022944}
        {0.053761}
        {0.058676}
        {0.091904}
        {0.023826}
        {0.042645}
        {0.050901}
        {0.040752}
        {0.051691}
        {0.068765}
        {0.058565}
        {0.066005}
        {0.014261}
        {0.032102}};

    model[utility.getGlobalValue("terms.model.efv_estimate_name")] = utility.getGlobalValue("terms.frequencies.predefined");
    (model[utility.getGlobalValue("terms.parameters")])[utility.getGlobalValue("terms.model.empirical")] = 0;
    return model;
}


