/*
    Theseus - maximum likelihood superpositioning of macromolecular structures

    Copyright (C) 2004-2015 Douglas L. Theobald

    This file is part of THESEUS.

    THESEUS is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as
    published by the Free Software Foundation, either version 3 of
    the License, or (at your option) any later version.

    THESEUS is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public
    License along with THESEUS in the file 'COPYING'. If not, see
    <http://www.gnu.org/licenses/>.

    -/_|:|_|_\-
*/

#ifndef DISTFIT_SEEN
#define DISTFIT_SEEN

//#include "bimultinom.h"
#include "DLTutils.h"
#include "DLTmath.h"
#include "distfit.h"
//#include "VecUtils.h"
//#include "integrate.h"
//#include "myrandom.h"
//#include "specfunc.h"
//#include "statistics.h"

//#include "beta_dist.h"
//#include "betasym_dist.h"
//#include "binomial_dist.h"
//#include "cauchy_dist.h"
//#include "chi_dist.h"
//#include "chisqr_dist.h"
//#include "chisqrgen_dist.h"
//#include "EVD_dist.h"
//#include "exp_dist.h"
//#include "gamma_dist.h"
//#include "invchisqr_dist.h"
//#include "invgamma_dist.h"
//#include "invgauss_dist.h"
//#include "laplace_dist.h"
//#include "logistic_dist.h"
//#include "lognormal_dist.h"
//#include "maxwell_dist.h"
//#include "negbinom_dist.h"
//#include "normal_dist.h"
//#include "pareto_dist.h"
//#include "recinvgauss_dist.h"
//#include "uniform_dist.h"
//#include "vonmises_dist.h"
//#include "weibull_dist.h"

typedef double (*DistFit)
(const double *data, const int ndata, double *param1, double *param2, double *logL);

typedef double (*DistDev)
(const double param1, const double param2, const gsl_rng *r2);

typedef double (*DistFitW)
(const double *data, const int ndata, const double *wts, double *param1,
 double *param2, double *logL);

typedef void (*InitMixParams)
(const double *data, const int ndata, const int mixn, double *param1, double *param2);

typedef double (*DistPDF)
(const double x, double param1, double param2);

typedef double (*DistCDF)
(const double x, double param1, double param2);

typedef double (*DistSDF)
(const double x, double param1, double param2);

typedef double (*DistInt)
(const double x, const double y, double param1, double param2);

double
DistFitMix(DistPDF distpdf, DistFitW distfitw, InitMixParams distinit,
           const double *x, const int n, const int mixn,
           double *param1, double *param2, double *mixp);

typedef struct
{
    char            dist_name[32];
    DistFit         distfit_func;
    DistDev         distdev_func;
    int             pnum;
    int             isneg;
    double          akaikewt, bayesprob;
} Distribution;

typedef struct
{
    DistFit         distfit_func;
    char            dist_name[32];
    double          param1, param2;
    double          chisq, logL, logLper, AIC, BIC;
    double          akaikewt, bayesprob;
} DistStats;

typedef struct
{
    unsigned long   seed;
    int             distnum;
    int             isbeta;
    int             isneg;
    int             iszero;
    int             distindex;
    int             bootstrap;
    int             histo;
    int             transform;
    int             col;
    int             length;
    double          p1, p2;
    int             distdev;
    int             randnum;
    int             mix;
    int             fixzeros;
    int             fixones;
    double          digamma;
    double          trigamma;
    double          invdigamma;
    int             neg;
    double          burnin;
} DFParams;


void
TestData(const double *data, const int length);

int
TestDistVsData(const int ndist);

void
PrintRandDist(char *fname, double (*dist_dev)(double param1, double param2, const gsl_rng *r2),
              double param1, double param2, int ndata, const unsigned long seed);

int
TransformData(int transform, double *array, double *warray, int length, int distnum);

void
MultiHistFit(double *array, double *freq, int length);

void
BootFit(DistStats **diststats, int distindex, double *array, int length, DFParams *dfparams);

void
SingleDistFit(DistFit *distfit_func, int distindex, char *dist_name,
              DistStats *diststats, double *array, int length, DFParams *dfparams);

void
MultiDistFit(DistFit *distfit_func, char dist_name[][32], DistStats **diststats,
             int distnum, double *array, int length, DFParams *dfparams);

int
UnbonkFits(DistStats **diststats, int distnum);

void
CalcAkaike(DistStats **diststats, int distnum);

void
PrintDistStats(DistStats **diststats, int distnum);

void
PrintDistSD(DistStats **diststats);

void
InsortDiststats(DistStats **diststats, int distnum);

void
printlist(double *list, int length);

void
Usage(void);

void
Version(void);

double
*getvals(char *listfile_name, int *length, int column);

int
gethistvals(FILE *listfile, double *data, double *freq, int length);

#endif
