// $Id: ModelDS.cpp,v 1.5 2018/01/03 21:32:57 mkkuhner Exp $

/*
Copyright 2002-2005 Mary K. Kuhner, Peter Beerli, and Joseph Felsenstein

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*/

/* Authors: Patrick Colacurcio, Peter Beerli, Mary Kuhner, Jon Yamato 
/* Authors: Patrick Colacurcio, Peter Beerli, Mary Kuhner, Jon Yamato 
and Joseph Felsenstein */


#include "Converter_ModelDS.h"
#include "Converter_DataSourceException.h"
#include "stringx.h"

#ifdef DMALLOC_FUNC_CHECK
#include "/usr/local/include/dmalloc.h"
#endif

using namespace std;

//------------------------------------------------------------------------------------

ModelDS::ModelDS()
    : m_modelName("F84"),
      m_ttRatio(2.0),
      m_numCategories(1),
      m_rates(1.0),
      m_probabilities(1.0)
{
    setFreqs(.25, .25, .25, .25);
}                               // ModelDS::ModelDS

ModelDS::ModelDS(const string& modelName,
                 const double freqA,
                 const double freqC,
                 const double freqG,
                 const double freqT,
                 const double ttRatio)
    : m_modelName(modelName),
      m_ttRatio(ttRatio),
      m_numCategories(1),
      m_rates(1.0),
      m_probabilities(1.0)
{
    setFreqs(freqA, freqC, freqG, freqT);
}                               // ModelDS::ModelDS

ModelDS::ModelDS(const string& modelName,
                 const double freqA,
                 const double freqC,
                 const double freqG,
                 const double freqT,
                 const double ttRatio,
                 const unsigned int numCategories,
                 const double rates,
                 const double probabilities)
    : m_modelName(modelName),
      m_ttRatio(ttRatio),
      m_numCategories(numCategories),
      m_rates(rates),
      m_probabilities(probabilities)
{
    setFreqs(freqA, freqC, freqG, freqT);
}                               // ModelDS::ModelDS

//------------------------------------------------------------------------------------

ModelDS::~ModelDS ()
{
}                               // ModelDS::~ModelDS

//------------------------------------------------------------------------------------

void
ModelDS::setFreqs(double freqA, double freqC, double freqG, double freqT)
{
    validateFreqs(freqA, freqC, freqG, freqT);

    // Push them onto the map
    m_freqs["A"] =  freqA;
    m_freqs["C"] =  freqC;
    m_freqs["G"] =  freqG;
    m_freqs["T"] =  freqT;
}

//------------------------------------------------------------------------------------

string
ModelDS::getName() const
{
    return m_modelName;
}

void
ModelDS::setName(const string& name)
{
    m_modelName = name;
}

//------------------------------------------------------------------------------------

double
ModelDS::getTTRatio() const
{
    return m_ttRatio;
}

void
ModelDS::setTTRatio(const double ttRatio)
{
    m_ttRatio = ttRatio;
}

//------------------------------------------------------------------------------------

unsigned int
ModelDS::getNumCategories() const
{
    return m_numCategories;
}

void
ModelDS::setNumCategories(const unsigned int numCategories)
{
    m_numCategories = numCategories;
}

//------------------------------------------------------------------------------------

double
ModelDS::getRates() const
{
    return m_rates;
}

void
ModelDS::setRates(const double rates)
{
    m_rates = rates;
}

//------------------------------------------------------------------------------------

double
ModelDS::getProbabilities() const
{
    return m_probabilities;
}

void
ModelDS::setProbabilities(const double probabilities)
{
    m_probabilities = probabilities;
}

//------------------------------------------------------------------------------------

double
ModelDS::getAFreq()
{
    return m_freqs["A"];
}

double
ModelDS::getCFreq()
{
    return m_freqs["C"];
}

double
ModelDS::getGFreq()
{
    return m_freqs["G"];
}

double
ModelDS::getTFreq()
{
    return m_freqs["T"];
}

//------------------------------------------------------------------------------------

void
ModelDS::validateFreqs(const double a,
                       const double g,
                       const double c,
                       const double t)
{
    //  map<string,double>::iterator pos;
    double sum = 0;

    //  for (pos = m_freqs.begin(); pos != m_freqs.end(); ++pos())
    //    {
    //      sum += pos->second;
    //    }
    sum = a + g + c + t;

    if (fabs(sum-1.0) > 0.001)  // Epsilon taken from /tree/interface.cpp
    {
        throw InvalidFrequenciesError("The frequencies don't add up to 1.");
    }
    else
        return;
}

//------------------------------------------------------------------------------------

string
ModelDS::getXML(unsigned int numTabs) const
{
    string modelXML;

    addTabs(numTabs, modelXML);
    modelXML = modelXML + "<model name=\"" + m_modelName + "\">\n";

    //  Now, lets write out all of this models individuals.

    ++numTabs;

    addTabs(numTabs, modelXML);
    map<string, double>::const_iterator i;
    modelXML += "<base-freqs> ";

    // These should be in order
    for (i = m_freqs.begin(); i != m_freqs.end(); i++)
    {
        modelXML += ToString(i->second);
        modelXML += " ";
    }

    modelXML += "</base-freqs>\n";

    addTabs(numTabs, modelXML);

    modelXML += "<ttratio> " + ToString(m_ttRatio) + " </ttratio>\n";

    addTabs(numTabs, modelXML);
    modelXML = modelXML + "<categories>\n";

    ++numTabs;
    addTabs(numTabs, modelXML);
    modelXML = modelXML + "<num-categories> " + ToString((int)m_numCategories) + " </num-categories>\n";

    addTabs(numTabs, modelXML);

    modelXML = modelXML + "<rates> " + ToString(m_rates) + " </rates>\n";

    addTabs(numTabs, modelXML);
    modelXML = modelXML + "<probabilities> " + ToString(m_probabilities) + " </probabilities>\n";

    --numTabs;
    addTabs(numTabs, modelXML);
    modelXML = modelXML + "</categories>\n";

    --numTabs;
    addTabs(numTabs, modelXML);
    modelXML += "</model>\n";

    return modelXML;
}

//____________________________________________________________________________________
