// $Id: bayesanalyzer_1d.h,v 1.20 2018/01/03 21:32:54 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: Lucian Smith, Mary Kuhner, Jon Yamato and Joseph Felsenstein */


/*
  The Bayesian analyzer holds vectors of 'BayesParamlike's, which are front
  ends, of a sort, for BayesCurves.  As the collection manager sends the
  BayesAnalyzer lists of parameters, it divvies up the information, and sends
  it to the appropriate BayesParamLike.  The ParamLikes then take the
  accumulated data points and curve-smooth them so that we know both the
  MLEs and the confidence intervals for all parameters.

  This can be accomplished by analyzing the parameters 1-, 2-, or
  n-dimensionally.  The simplest is 1-dimensionally, where we look at each
  parameter without regard to how it might affect other parameters.  At the
  next level, we might consider pairs of parameters, and smooth the
  resulting 2-dimensional surface.  Finally, we might attempt to go for the
  gusto and consider all parameters at once, smoothing an n-dimensional
  surface.  Such a surface would be nigh-impossible to visualize, and trying
  to find the maximum on such a surface would probably be as difficult as
  normal maximization.  Perhaps the maximizer object could do such a
  maximization, given a different PLforces object, or some such.  Anyway.

  As a first pass at attempting to do this, we'll be analyzing the parameters
  individually with Bayes_Analyzer_1D.  In the future, we might try the
  other two options (_2D and _ND, respectively).

  It might be interesting to look at this in terms of Singular Value
  Decomposition, or SVD.  This is what folks at Rice did with protein
  dynamics.
*/

#ifndef BAYES_ANALYZER_H
#define BAYES_ANALYZER_H

#include "vectorx.h"
#include "collector.h"
#include "bayesparamlike_1d.h"
#include "bayescurve.h"
#include "forcesummary.h"
#include "parameter.h"
#include "paramstat.h"

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

class BayesAnalyzer_1D
{
  public:
    //   ---Generic BayesAnalyzer functions---
    BayesAnalyzer_1D();
    ~BayesAnalyzer_1D();

    void AnalyzeAndAdd(const ParamSumm paramsumm);
    void ReplaceLastChainAndAnalyze(const ParamSumm paramsumm);
    //You might call the Replace routine if you do a run with more than one
    // chain, but wanted to analyze the first chain.
    void EndChainsAndAnalyze();
    void EndReplicatesAndAnalyze();
    void EndRegionsAndAnalyze();

    //   ---Functions specific to a 1D analysis---
    DoubleVec1d GetMaxVecForLastChain();
    double      GetAvgMaxLikeForLastChain();
    double      GetAvgMaxLikeForRegion(long int region);
    double      GetAvgMaxLikeForAllRegions();

    double      GetMaxForChain(long int chain, long int parameter);
    double      GetLikeAtMaxForChain(long int chain, long int parameter);

    double      GetMaxForRegion(long int region, long int parameter);
    DoubleVec1d GetMaxVecForRegion(long int region);

    double      GetLikeAtMaxForRegion(long int region, long int parameter);
    double      GetValAtPercentileForRegion(double percentile, long int region, long int parameter);
    double      GetPercentileAtValForRegion(double val, long int region, long int parameter);
    double      GetLikeAtValForRegion(double val, long int region, long int parameter);
    double      GetLikeAtValForReplicate(double val, long int region, long int replicate, long int parameter);

    double      GetMaxForAllRegions(long int parameter);
    DoubleVec1d GetMaxVecForAllRegions();
    double      GetLikeAtMaxForAllRegions(long int parameter);
    double      GetValAtPercentileForAllRegions(double percentile, long int parameter);
    double      GetPercentileAtValForAllRegions(double val, long int parameter);
    double      GetLikeAtValForAllRegions(double val, long int parameter);

    double      GetMinParamValFromCurve(long int region, long int parameter);
    double      GetMaxParamValFromCurve(long int region, long int parameter);
    double      GetBinWidthFromCurve   (long int region, long int parameter);

    bool        GetIsLog(long int parameter);

    long int    GetNumUniquePoints(long int parameter);
    double      GetKernelWidth(long int parameter);

    void CalcProfiles(long int region);
    std::vector <long int> GetNumUniquePointsVec();
    void WriteCurvesForRegion (long int region);

  private:
    long int m_currentChain;
    long int m_currentReplicate;
    long int m_currentRegion;

    const ForceSummary &m_forcesummary;

    vector <ParamStatus> m_pstats;
    DoubleVec1d m_startparams;

    //The chain curves are stored in the vector of BayesParamLikes, while
    // the region and overall curves are stored as BayesCurve member variables.
    vector < vector <BayesParamLike_1D> >  m_paramlikes;
    //Dimensions are m_paramlikes[chain][parameter]
    vector < vector < vector < BayesCurve> > > m_replicatecurves;
    //Dimensions are [region][replicate][parameter]
    vector < vector <BayesCurve> >  m_regioncurves;
    //Dimensions are m_regioncurves[region][parameter]
    vector <BayesCurve>  m_allregioncurves;
    //Dimensions are m_allregioncurves[parameter]

    vector <BayesParamLike_1D> m_blankBayesParamVec;
    //This is created at object creation, initialized with the appropriate
    // forces in the correct orders, since BayesParamLike_1D's can only be
    // created knowing what force they're for.

    bool IsVariable(unsigned long int parameter);
    void CalcProfile(ParamVector::iterator param, long int nparam, long int nregion);

}; // class BayesAnalyzer_1D

#endif // BAYES_ANALYZER_H

//____________________________________________________________________________________
