// $Id: ui_vars_datamodel.h,v 1.25 2018/01/03 21:33:05 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: Peter Beerli, Mary Kuhner, Jon Yamato and Joseph Felsenstein */


#ifndef UI_VARS_DATAMODEL_H
#define UI_VARS_DATAMODEL_H

#include <deque>
#include <vector>

#include "constants.h"          // for model_type
#include "types.h"
#include "vectorx.h"            // for DoubleVec1d
#include "ui_vars_component.h"
#include "datatype.h"           // for data_type

class UIRegId;

using std::deque;
using std::vector;

class UIVarsDataModels;

class UIVarsSingleDataModel
{
    friend class UIVarsDataModels;

  private:
    UIVarsSingleDataModel();    // undefined
    long            m_regionIndex;
    long            m_locusIndex;
    data_type       m_datatype;
    model_type      m_modelType;
    bool            doNormalize;
    double          autoCorrelation;
    DoubleVec1d     categoryRates;
    DoubleVec1d     categoryProbabilities;
    double          ttRatio;
    bool            doCalcFreqsFromData;
    double          baseFrequency_A;
    double          baseFrequency_C;
    double          baseFrequency_G;
    double          baseFrequency_T;
    double          gtr_AC;
    double          gtr_AG;
    double          gtr_AT;
    double          gtr_CG;
    double          gtr_CT;
    double          gtr_GT;
    double          alpha;
    double          m_relmurate;
    bool            optimizeAlpha;
    double          m_perBaseErrorRate;
    double MakeNextCategoryProbability(DoubleVec1d probabilities);
    double MakeNextCategoryRate(DoubleVec1d rates);

    //protected:
    void CalculateFrequenciesFromData();

    //public:
    UIVarsSingleDataModel(UIRegId regionId);
    UIVarsSingleDataModel(const UIVarsSingleDataModel& clone, UIRegId regionId);

    /////////////////////////////////////////////////////////////
    virtual data_type   GetDataType()           const {return m_datatype;};
    virtual model_type  GetDataModelType()      const {return m_modelType;};
    virtual bool        GetNormalization()      const {return doNormalize;};
    virtual double      GetAutoCorrelation()    const {return autoCorrelation;};
    virtual long        GetNumCategories()      const;
    virtual double      GetCategoryRate(long categoryIndex) const;
    virtual DoubleVec1d GetCategoryRates()      const {return categoryRates;};
    virtual DoubleVec1d GetCategoryProbabilities()  const {return categoryProbabilities;};
    virtual double      GetCategoryProbability(long categoryIndex) const;
    virtual double      GetTTRatio()            const {return ttRatio;};
    virtual bool        GetCalcFreqsFromData()  const;
    virtual double      GetFrequencyA()         const;
    virtual double      GetFrequencyC()         const;
    virtual double      GetFrequencyG()         const;
    virtual double      GetFrequencyT()         const;
    virtual double      GetGTR_AC()             const {return gtr_AC;};
    virtual double      GetGTR_AG()             const {return gtr_AG;};
    virtual double      GetGTR_AT()             const {return gtr_AT;};
    virtual double      GetGTR_CG()             const {return gtr_CG;};
    virtual double      GetGTR_CT()             const {return gtr_CT;};
    virtual double      GetGTR_GT()             const {return gtr_GT;};
    virtual double      GetAlpha()              const {return alpha;};
    virtual double      GetRelativeMuRate()     const {return m_relmurate;};
    virtual bool        GetOptimizeAlpha()      const {return optimizeAlpha;};
    virtual double      GetPerBaseErrorRate()   const {return m_perBaseErrorRate;};

    /////////////////////////////////////////////////////////////
    virtual void SetDataModelType(model_type x);
    virtual void SetNormalization(bool x)       {doNormalize = x;};
    virtual void SetAutoCorrelation(double x);
    virtual void SetNumCategories(long x);
    virtual void SetCategoryRate(double x, long index);
    virtual void SetCategoryProbability(double x, long index);
    virtual void SetTTRatio(double x);
    virtual void SetCalcFreqsFromData(bool x);
    virtual void SetFrequencyA(double x);
    virtual void SetFrequencyC(double x);
    virtual void SetFrequencyG(double x);
    virtual void SetFrequencyT(double x);
    virtual void SetGTR_AT(double x);
    virtual void SetGTR_AC(double x);
    virtual void SetGTR_AG(double x);
    virtual void SetGTR_CG(double x);
    virtual void SetGTR_CT(double x);
    virtual void SetGTR_GT(double x);
    virtual void SetRelativeMuRate(double x);
    virtual void SetAlpha(double x);
    virtual void SetOptimizeAlpha(bool x)       {optimizeAlpha = x;};
    virtual void SetPerBaseErrorRate(double x)  {m_perBaseErrorRate = x;};

    virtual bool IdenticalCategoryRates() const;

  public:
    virtual ~UIVarsSingleDataModel();

};

class UIVarsDataModels : public UIVarsComponent
{
  private:
    UIVarsSingleDataModel           m_globalModelNucleotide;
    UIVarsSingleDataModel           m_globalModelMsat;
    UIVarsSingleDataModel           m_globalModelKAllele;
    vector< deque<bool> >                     m_useGlobalModel;
    vector< vector<UIVarsSingleDataModel> >   m_individualModels;
    UIVarsDataModels();              // undefined
    UIVarsDataModels(const UIVarsDataModels&);              // undefined

    class ModelIsIllegalForDataType : public std::unary_function<model_type,bool>
    {
      private:
        data_type m_dtype;
      public:
        ModelIsIllegalForDataType(data_type dtype);
        ~ModelIsIllegalForDataType();
        bool operator()(model_type mtype) const;
    };

  protected:
    virtual void checkRegionIdGlobalAllowed(UIRegId regionId) const;
    virtual void checkRegionIdGlobalNotAllowed(UIRegId regionId) const;
    virtual UIVarsSingleDataModel & getRegionModelToAlter(UIRegId regionId);
    virtual bool returnLocalCalcedFreqWithGlobalModel(UIRegId regionId) const;
    virtual double adjustZeroFrequency(double mightBeZero);

  public:
    // one might argue that the constructors should have
    // restricted access since only UIVars should
    // be creating these puppies.
    UIVarsDataModels(UIVars*,long nregions,long maxLoci);
    UIVarsDataModels(UIVars*,const UIVarsDataModels&);
    virtual void Initialize();
    virtual ~UIVarsDataModels();

    virtual bool GetUseGlobalModel(UIRegId regionId) const;
    virtual const UIVarsSingleDataModel & GetRegionModel(UIRegId regionId) const;
    virtual const UIVarsSingleDataModel & GetGlobalModel(data_type) const;

    virtual data_type   GetDataType(UIRegId regionId) const;
    virtual model_type  GetDataModelType(UIRegId regionId) const;
    virtual bool        GetNormalization(UIRegId regionId) const;
    virtual double      GetAutoCorrelation(UIRegId regionId) const;
    virtual long        GetNumCategories(UIRegId regionId) const;
    virtual double      GetCategoryRate(UIRegId regionId, long categoryIndex) const;
    virtual DoubleVec1d GetCategoryRates(UIRegId regionId) const;
    virtual DoubleVec1d GetCategoryProbabilities(UIRegId regionId) const;
    virtual double      GetCategoryProbability(UIRegId regionId, long categoryIndex) const;
    virtual double      GetTTRatio(UIRegId regionId) const;
    virtual bool        GetCalcFreqsFromData(UIRegId regionId) const;
    virtual double      GetFrequencyA(UIRegId regionId) const;
    virtual double      GetFrequencyC(UIRegId regionId) const;
    virtual double      GetFrequencyG(UIRegId regionId) const;
    virtual double      GetFrequencyT(UIRegId regionId) const;
    virtual double      GetGTR_AC(UIRegId regionId) const;
    virtual double      GetGTR_AG(UIRegId regionId) const;
    virtual double      GetGTR_AT(UIRegId regionId) const;
    virtual double      GetGTR_CG(UIRegId regionId) const;
    virtual double      GetGTR_CT(UIRegId regionId) const;
    virtual double      GetGTR_GT(UIRegId regionId) const;
    virtual double      GetAlpha(UIRegId regionId) const;
    virtual double      GetRelativeMuRate(UIRegId regionId) const;
    virtual DoubleVec2d GetRelativeMuRates() const;
    virtual bool        GetOptimizeAlpha(UIRegId regionId) const;
    virtual double      GetPerBaseErrorRate(UIRegId regionId) const;
    virtual StringVec1d GetDataModelReport(UIRegId regionId) const;
    virtual ModelTypeVec1d  GetLegalDataModels(UIRegId regionId) const;

    virtual bool IdenticalCategoryRates(UIRegId regionId) const;

    virtual void SetUseGlobalModel(bool x, UIRegId regionId);
    virtual void SetDataModelType(model_type x, UIRegId regionId);
    virtual void SetNormalization(bool x, UIRegId regionId);
    virtual void SetAutoCorrelation(double x, UIRegId regionId);
    virtual void SetNumCategories(long x, UIRegId regionId);
    virtual void SetCategoryRate(double x, UIRegId regionId, long categoryIndex);
    virtual void SetCategoryProbability(double x, UIRegId regionId, long categoryIndex);
    virtual void SetTTRatio(double x, UIRegId regionId);
    virtual void SetCalcFreqsFromData(bool x, UIRegId regionId);
    virtual void SetFrequencyA(double x, UIRegId regionId);
    virtual void SetFrequencyC(double x, UIRegId regionId);
    virtual void SetFrequencyG(double x, UIRegId regionId);
    virtual void SetFrequencyT(double x, UIRegId regionId);
    virtual void SetGTR_AT(double x, UIRegId regionId);
    virtual void SetGTR_AC(double x, UIRegId regionId);
    virtual void SetGTR_AG(double x, UIRegId regionId);
    virtual void SetGTR_CG(double x, UIRegId regionId);
    virtual void SetGTR_CT(double x, UIRegId regionId);
    virtual void SetGTR_GT(double x, UIRegId regionId);
    virtual void SetRelativeMuRate(double x, UIRegId regionId);
    virtual void SetAlpha(double x, UIRegId regionId);
    virtual void SetOptimizeAlpha(bool x, UIRegId regionId);
    virtual void SetPerBaseErrorRate(double x, UIRegId regionId);

    virtual void SetAllRegionsToGlobalModel();
};

#endif  // UI_VARS_DATAMODEL_H

//____________________________________________________________________________________
