39 using namespace random;
47 function<double(
double)> f_moment = [
this] (
double x) {
return this->operator()(x);};
57 function<double(
double)> f = bind(m_func, std::placeholders::_1, m_distribution_func_fixed_pars, m_distribution_func_pars);
60 m_log_distribution_normalization = log(m_distribution_normalization);
69 if (distributionType!=glob::DistributionType::_Constant_)
70 ErrorCBL(
"this constructor only allows DistributionType::_Constant_ !",
"Distribution",
"Distribution.cpp");
72 set_constant_distribution(value);
82 if (distributionType != glob::DistributionType::_Uniform_)
83 ErrorCBL(
"this constructor only allows DistributionType::_Uniform_ !",
"Distribution",
"Distribution.cpp");
85 set_uniform_distribution(xmin, xmax, seed);
94 set_limits(xmin, xmax);
96 if (distributionType == glob::DistributionType::_Gaussian_) {
97 if (distribution_params.size() != 2)
98 ErrorCBL(
"wrong size of distribution_params: Gaussian distribution needs 2 parameters, the mean and the standard deviation!",
"Distribution",
"Distribution.cpp");
100 set_gaussian_distribution(distribution_params[0], distribution_params[1], seed);
103 else if (distributionType == glob::DistributionType::_Poisson_) {
104 if (distribution_params.size() != 1)
105 ErrorCBL(
"wrong size of distribution_params: poisson distribution needs 1 parameter, the mean",
"Distribution",
"Distribution.cpp");
107 set_poisson_distribution(distribution_params[0], seed);
111 ErrorCBL(
"no such type of distribution",
"Distribution",
"Distribution.cpp");
120 set_limits(xmin, xmax);
122 if (distributionType != glob::DistributionType::_Custom_)
123 ErrorCBL(
"this constructor only allows DistributionType::_Custom_ !",
"Distribution",
"Distribution.cpp");
125 set_custom_distribution(func, distribution_fixed_pars, distribution_pars, seed);
134 if (distributionType != glob::DistributionType::_Discrete_)
135 ErrorCBL(
"this constructor only allows DistributionType::_Discrete_ !",
"Distribution",
"Distribution.cpp");
137 set_discrete_values(discrete_values, weights, seed);
146 if (distributionType == glob::DistributionType::_Discrete_)
148 vector<double> vv, dd, edd;
149 get_distribution(vv, dd, edd, var, dist, nbin);
151 set_binned_distribution(vv, dd, interpolationType, seed);
153 else if (distributionType == glob::DistributionType::_Interpolated_)
155 set_binned_distribution(var, dist, interpolationType, seed);
158 ErrorCBL(
"no such type of distribution",
"Distribution",
"Distribution.cpp");
167 if (xx<m_xmin || xx>m_xmax)
return 0;
168 else return m_func(xx, m_distribution_func_fixed_pars, m_distribution_func_pars)/m_distribution_normalization;
178 else return log(m_func(xx, m_distribution_func_fixed_pars, m_distribution_func_pars))-m_log_distribution_normalization;
197 m_distributionType = glob::DistributionType::_Constant_;
203 m_func = &identity<double>;
204 m_distribution_normalization = 1.;
205 m_log_distribution_normalization = 0.;
214 m_distributionType = glob::DistributionType::_Uniform_;
216 set_limits(xmin, xmax);
217 m_distribution_func_pars.erase(m_distribution_func_pars.begin(), m_distribution_func_pars.end());
219 m_distribution_func_pars.push_back(m_xmax);
220 m_distribution_func_pars.push_back(m_xmax);
222 m_distribution_random = make_shared<UniformRandomNumbers> (
UniformRandomNumbers(m_xmin, m_xmax, seed));
223 m_func = &identity<double>;
225 m_distribution_normalization = m_xmax-m_xmin;
226 m_log_distribution_normalization = log(m_xmax-m_xmin);
235 m_distributionType = glob::DistributionType::_Gaussian_;
237 m_distribution_func_pars.erase(m_distribution_func_pars.begin(), m_distribution_func_pars.end());
238 m_distribution_func_pars.push_back(mean);
239 m_distribution_func_pars.push_back(sigma);
241 m_distribution_random = make_shared<NormalRandomNumbers> (
NormalRandomNumbers(mean, sigma, seed, m_xmin, m_xmax));
242 m_func = &gaussian<double>;
247 m_distribution_normalization = 0.5*(erf((m_xmax-mean)/sigma/sqrt(2.))-erf((m_xmin-mean)/sigma/sqrt(2.)));
248 m_log_distribution_normalization = log(m_distribution_normalization);
258 m_distributionType = glob::DistributionType::_Poisson_;
260 m_xmin =
nint(m_xmin);
261 m_xmax =
nint(m_xmax);
262 int nbins = m_xmax-m_xmin;
265 vector<double> weights;
266 for(
int i=0;i<nbins;i++)
267 weights.push_back(
poisson(poisson_values[i],NULL,{mean}));
269 m_distribution_random = make_shared<DiscreteRandomNumbers> (
DiscreteRandomNumbers(poisson_values, weights, seed, m_xmin, m_xmax));
271 glob::STR_closest_probability parameters;
272 parameters.values = poisson_values;
273 parameters.weights = weights;
275 m_distribution_func_fixed_pars = make_shared<glob::STR_closest_probability>(parameters);
278 m_distribution_normalization = accumulate(weights.begin(), weights.end(), 0);
279 m_log_distribution_normalization = log(m_distribution_normalization);
288 m_distributionType = glob::DistributionType::_Discrete_;
290 if (discrete_values.size()==0)
291 ErrorCBL(
"the input vector of discrete values is empty",
"set_discrete_values",
"Distribution.cpp");
293 set_limits(
Min(discrete_values),
Max(discrete_values));
295 m_distribution_random = make_shared<DiscreteRandomNumbers> (
DiscreteRandomNumbers(discrete_values, weights, seed, m_xmin, m_xmax));
297 vector<double> ww = weights;
300 ww.resize(discrete_values.size(), 1);
302 glob::STR_closest_probability parameters;
303 parameters.values = discrete_values;
304 parameters.weights = ww;
306 m_distribution_func_fixed_pars = make_shared<glob::STR_closest_probability>(parameters);
309 m_distribution_normalization = accumulate(ww.begin(), ww.end(), 0);
310 m_log_distribution_normalization = log(m_distribution_normalization);
320 m_distributionType = glob::DistributionType::_Custom_;
323 m_distribution_func_fixed_pars = distribution_fixed_pars;
324 m_distribution_func_pars = distribution_pars;
326 m_distribution_random = make_shared<CustomDistributionRandomNumbers> (
CustomDistributionRandomNumbers(m_func, m_distribution_func_fixed_pars, m_distribution_func_pars, seed, m_xmin, m_xmax));
328 m_set_distribution_normalization();
338 m_distributionType = glob::DistributionType::_Interpolated_;
341 ErrorCBL(
"the input vector is empty",
"set_binned_distribution",
"Distribution.cpp");
343 set_limits(
Min(var),
Max(var));
344 m_distribution_random = make_shared<DistributionRandomNumbers> (
DistributionRandomNumbers(var, dist, interpolationType, seed));
346 glob::STR_distribution_probability parameters;
347 parameters.func = make_shared<glob::FuncGrid>(
glob::FuncGrid(var, dist, interpolationType));
349 m_distribution_func_fixed_pars = make_shared<glob::STR_distribution_probability>(parameters);
352 m_set_distribution_normalization();
361 if (value > m_xmin && m_xmax > value)
373 double value = m_distribution_random->operator()();
374 while (!isIncluded(value))
375 value = m_distribution_random->operator()();
385 m_distribution_random->set_seed(seed);
395 vector<double> values;
397 for (
int i=0; i<nvalues; i++)
398 values.push_back(sample());
412 if (m_distributionType == glob::DistributionType::_Discrete_) {
413 shared_ptr<STR_closest_probability> pp = static_pointer_cast<glob::STR_closest_probability>(m_distribution_func_fixed_pars);
414 val =
Average(pp->values, pp->weights);
418 function<double(
double)> f = bind(&Distribution::m_moments_integrator,
this, std::placeholders::_1, 1);
434 if (m_distributionType == glob::DistributionType::_Discrete_) {
435 shared_ptr<STR_closest_probability> pp = static_pointer_cast<glob::STR_closest_probability>(m_distribution_func_fixed_pars);
436 val = pow(
Sigma(pp->values, pp->weights),2);
442 function<double(
double)> f = [
this] (
double xx) {
return this->m_central_moments_integrator(xx, 2);};
456 return sqrt(variance());
467 if (m_distributionType == glob::DistributionType::_Discrete_)
468 ErrorCBL(
"",
"skewness",
"Distribution.cpp", glob::ExitCode::_workInProgress_);
473 function<double(
double)> f = [
this] (
double xx) {
return this->m_central_moments_integrator(xx, 3); };
489 if (m_distributionType == glob::DistributionType::_Discrete_)
490 ErrorCBL(
"",
"kurtosis",
"Distribution.cpp", glob::ExitCode::_workInProgress_);
495 function<double(
double)> f = [
this] (
double xx) {
return this->m_central_moments_integrator(xx, 4); };
509 return {mean(), std(), skewness(), kurtosis()};
518 double Area = double(i)/100.;
521 if (m_distributionType == glob::DistributionType::_Discrete_) {
522 shared_ptr<STR_closest_probability> pp = static_pointer_cast<glob::STR_closest_probability>(m_distribution_func_fixed_pars);
523 vector<double> vv = pp->values; sort(vv.begin(), vv.end());
524 int perc =
nint(
double(i)/100.*pp->values.size());
529 function<double(
double)> f_integral = [
this] (
double xx) {
return this->m_percentile_integrator(xx); };
545 if (m_distributionType == glob::DistributionType::_Discrete_) {
548 shared_ptr<STR_closest_probability> pp = static_pointer_cast<glob::STR_closest_probability>(m_distribution_func_fixed_pars);
549 vector<double> vv = pp->values;
550 for (
size_t i=0; i<vv.size(); i++)
553 vector<double> unique_vv = vv;
555 sort(unique_vv.begin(), unique_vv.end());
558 for (
size_t i=0; i<unique_vv.size(); i++) {
559 int cc = std::count(vv.begin(), vv.end(), unique_vv[i]);
568 auto func = [&] (
const double param) {
return -this->operator()(param); };
569 double start = median();
580 void cbl::glob::Distribution::get_distribution (vector<double> &xx, vector<double> &fx, vector<double> &err,
const std::vector<double> FF,
const std::vector<double> WW,
const int nbin,
const bool linear,
const std::string file_out,
const double fact,
const double V1,
const double V2,
const bool bin_type,
const bool conv,
const double sigma)
582 if (xx.size()>0 || fx.size()>0 || FF.size()<=0 || nbin<=0)
ErrorCBL(
"the following conditions have to be satisfied: xx.size()<=0, fx.size()<=0, FF.size()>0 and nbin>0. The values recived are instead: xx.size() = "+
cbl::conv(xx.size(),
par::fINT)+
", fx.size() = "+
cbl::conv(fx.size(),
par::fINT)+
", FF.size() = "+
cbl::conv(FF.size(),
par::fINT)+
" and nbin = "+
cbl::conv(nbin,
par::fINT)+
"!",
"get_distribution",
"Distribution.cpp");
590 gsl_histogram *histo = gsl_histogram_alloc(nbin);
592 if (linear) gsl_histogram_set_ranges_uniform(histo, minFF, maxFF);
596 double *vvv =
new double[nbin+1];
for (
int i=0; i<nbin+1; i++) vvv[i] = vv[i];
597 gsl_histogram_set_ranges(histo, vvv, nbin+1);
600 vector<double> Weight = WW;
601 if (Weight.size()==0) Weight.resize(FF.size(), 1.);
604 for (
size_t i=0; i<FF.size(); i++)
605 gsl_histogram_accumulate(histo, FF[i], Weight[i]);
609 for (
int i=0; i<nbin; i++) {
611 gsl_histogram_get_range(histo, i, &x1, &x2);
612 double val = gsl_histogram_get(histo, i);
614 if (linear) xx.push_back(0.5*(x1+x2));
615 else xx.push_back(pow(10., 0.5*(log10(x1)+log10(x2))));
618 fx.push_back(val/((x2-x1)*fact));
619 err.push_back(sqrt(val)/((x2-x1)*fact));
622 fx.push_back(val/((log10(x2)-log10(x1))*fact));
623 err.push_back(sqrt(val)/((log10(x2)-log10(x1))*fact));
632 coutCBL <<
"The distribution is smoothed with a Gaussian filter" << endl;
634 fftw_complex *func_tr;
636 if (!linear)
ErrorCBL(
"",
"get_distribution",
"Distribution.cpp", ExitCode::_workInProgress_);
638 int i1 = nbin*0.5, i2 = 1.5*nbin;
640 int nbinK = 0.5*nbinN+1;
642 func = fftw_alloc_real(nbinN);
643 func_tr = fftw_alloc_complex(nbinK);
645 for (
int i=0; i<nbinN; i++)
648 for (
int i=i1; i<i2; i++)
651 for (
int i=0; i<nbinK; i++) {
656 fftw_plan real2complex;
657 real2complex = fftw_plan_dft_r2c_1d(nbinN, func, func_tr, FFTW_ESTIMATE);
658 fftw_execute(real2complex);
659 fftw_destroy_plan(real2complex);
661 double delta = (maxFF-minFF)/nbin;
662 double SS = pow(sigma,2);
664 double fact = 2*
par::pi/(nbinN*delta);
665 for (
int i=0; i<nbinK; i++) {
667 func_tr[i][0] = func_tr[i][0]*exp(-0.5*kk*kk*SS);
668 func_tr[i][1] = func_tr[i][1]*exp(-0.5*kk*kk*SS);
671 fftw_plan complex2real;
672 complex2real = fftw_plan_dft_c2r_1d(nbinN, func_tr, func, FFTW_ESTIMATE);
673 fftw_execute(complex2real);
674 fftw_destroy_plan(complex2real);
676 for (
int i=i1; i<i2; i++)
677 fx[i-i1] = func[i]/nbinN;
683 ofstream fout(file_out.c_str());
checkIO(fout, file_out);
685 for (
size_t i=0; i<xx.size(); i++)
686 fout << xx[i] <<
" " << fx[i] <<
" " << err[i] << endl;
688 fout.clear(); fout.close();
coutCBL <<
"I wrote the file: " << file_out << endl;
691 gsl_histogram_free(histo);
#define coutCBL
CBL print message.
void set_gaussian_distribution(const double mean, const double sigma, const int seed=1)
set normal distribution
void set_custom_distribution(const distribution_func func, const std::shared_ptr< void > distribution_fixed_pars, const std::vector< double > distribution_pars, const int seed=1)
set a custom distribution
void m_set_distribution_normalization()
set distribution normalization
double operator()(double xx)
evaluate distribution
void set_poisson_distribution(const double mean, const int seed=1)
set poisson distribution
double mean()
return the mean value of the distribution
double mode()
return the distribution mode
void set_constant_distribution(const double value)
set a constant distribution
Distribution()
default constructor
void set_limits(const double xmin, const double xmax)
set the distribution limits
double log_distribution(double xx)
evaluate log-distribution
double kurtosis()
return the kurtosis of the distribution
std::vector< double > moments()
return the moments of the distribution distribution
double variance()
return the standard deviation of the distribution
double skewness()
return the skewness of the distribution
double sample() const
sample a value from the distribution
void set_uniform_distribution(const double xmin, const double xmax, const int seed=1)
set an uniform distribution with input limits and seed
void set_discrete_values(const std::vector< double > discrete_values, const std::vector< double > weights, const int seed=1)
set discrete distribution values and weights
double std()
return the standard deviation of the distribution
void get_distribution(std::vector< double > &xx, std::vector< double > &fx, std::vector< double > &err, const std::vector< double > FF, const std::vector< double > WW, const int nbin, const bool linear=true, const std::string file_out=par::defaultString, const double fact=1., const double V1=par::defaultDouble, const double V2=par::defaultDouble, const bool bin_type=true, const bool conv=false, const double sigma=0.)
derive and store the number distribution of a given std::vector
double m_percentile_integrator(const double xx)
integrand of the percentile of the distribution
void set_binned_distribution(const std::vector< double > var, const std::vector< double > dist, const std::string interpolationType="Spline", const int seed=1)
set discrete distribution values and weights
bool isIncluded(const double value) const
check if a value is included in the distribution limits
double percentile(const unsigned int i)
return the i-th percentile of the distribution
std::vector< double > sample_vector(const int nvalues)
sample values from the distribution
The class ConstantRandomNumbers.
The class CustomDistributionRandomNumbers.
The class DiscreteRandomNumbers.
The class DistributionRandomNumbers.
The class NormalRandomNumbers.
static const char fINT[]
conversion symbol for: int -> std::string
static const std::string defaultString
default std::string value
static const double defaultDouble
default double value
static const double pi
: the ratio of a circle's circumference to its diameter
static const double cc
: the speed of light in vacuum (the value is exact) [km/sec]
DistributionType
the distribution type
double GSL_minimize_1D(FunctionDoubleDouble func, const double start, double min=par::defaultDouble, double max=-par::defaultDouble, const int max_iter=1000, const bool verbose=false)
minimize the provided function using GSL procedure
double GSL_integrate_cquad(gsl_function func, const double a, const double b, const double rel_err=1.e-3, const double abs_err=0, const int nevals=100)
integral, using the gsl cquad method
double GSL_root_brent(gsl_function Func, const double low_guess, const double up_guess, const double rel_err=1.e-3, const double abs_err=0)
function to find roots using GSL qag method
double GSL_integrate_qag(gsl_function Func, const double a, const double b, const double rel_err=1.e-3, const double abs_err=0, const int limit_size=1000, const int rule=6)
integral, computed using the GSL qag method
The global namespace of the CosmoBolognaLib
T Min(const std::vector< T > vect)
minimum element of a std::vector
std::string conv(const T val, const char *fact)
convert a number to a std::string
double Average(const std::vector< double > vect)
the average of a std::vector
std::vector< T > logarithmic_bin_vector(const size_t nn, const T min, const T max)
fill a std::vector with logarithmically spaced values
std::vector< T > linear_bin_vector(const size_t nn, const T min, const T max)
fill a std::vector with linearly spaced values
void checkDim(const std::vector< T > vect, const int val, const std::string vector, bool equal=true)
check if the dimension of a std::vector is equal/lower than an input value
void checkIO(const std::ifstream &fin, const std::string file="NULL")
check if an input file can be opened
int ErrorCBL(const std::string msg, const std::string functionCBL, const std::string fileCBL, const cbl::glob::ExitCode exitCode=cbl::glob::ExitCode::_error_)
throw an exception: it is used for handling exceptions inside the CosmoBolognaLib
void unique_unsorted(std::vector< int > &vv)
erase all the equal elements of the input std::vector
T poisson(T xx, std::shared_ptr< void > pp, std::vector< double > par)
the poisson distribution
T Max(const std::vector< T > vect)
maximum element of a std::vector
double Sigma(const std::vector< double > vect)
the standard deviation of a std::vector
std::function< double(double, std::shared_ptr< void >, std::vector< double >)> distribution_func
generic distribution function
double closest_probability(double xx, std::shared_ptr< void > pp, std::vector< double > par)
probability of the closest element to x from a list with weights
int nint(const T val)
the nearest integer
double round_to_precision(const double num, const int ndigits)
reduce the precision of an input double
double distribution_probability(double xx, std::shared_ptr< void > pp, std::vector< double > par)
probability of an interpolated distribution