"""
Standard Random sampling
========================

To calculate the coefficients of the gPC matrix, a number of model evaluations need to be
performed to sample the probability space :math:`\\Theta` and enable the estimation of the
polynomials. As for the computation of the coefficients, the input parameters :math:`\\mathbf{\\xi}`
can be sampled in a number of different ways. In **pygpc** the grid :math:`\\mathcal{G}` for this
application is constructed in `pygpc/Grid.py <../../../../pygpc/Grid.py>`_.

Example
-------
In order to create a grid of sampling points, we have to define the random parameters first.
"""

import pygpc
import numpy as np
import matplotlib.pyplot as plt
from collections import OrderedDict

# define random parameters
parameters = OrderedDict()
parameters["x1"] = pygpc.Beta(pdf_shape=[1, 1], pdf_limits=[-np.pi, np.pi])
parameters["x2"] = pygpc.Beta(pdf_shape=[1, 1], pdf_limits=[-np.pi, np.pi])

# In the case of random sampling the samples will be randomly drawn according to the probability density function (PDF)
# :math:`f(\xi)` of the input parameters.
#
# A simple random grid containing 200 sampling points can be generated by:

grid = pygpc.Random(parameters_random=parameters,
                    n_grid=200,
                    options={"seed": None})

# The following options are available for Random grids:
#
# - seed: set a seed to reproduce the grid
#
# The grid points are distributed as follows (in the normalized space between [-1, 1]):

fig = plt.figure(figsize=(4, 3.5))
plt.scatter(grid.coords_norm[:, 0], grid.coords_norm[:, 1], c="k")
plt.xlabel("$x_1$", fontsize=12)
plt.ylabel("$x_2$", fontsize=12)
plt.xlim([-1, 1])
plt.ylim([-1, 1])
plt.xticks(np.linspace(-1, 1, 5))
plt.yticks(np.linspace(-1, 1, 5))
plt.grid()
plt.tight_layout()

# For each gPC algorithm, the sampling method can be selected accordingly by setting the following options
# when setting up the algorithm:
options = dict()
...
options["grid"] = pygpc.Random
options["grid_options"] = {"seed": None}
...

# When using Windows you need to encapsulate the code in a main function and insert an
# if __name__ == '__main__': guard in the main module to avoid creating subprocesses recursively:
#
# if __name__ == '__main__':
#     main()
