Ejemplo n.º 1
0
 def test_construct_fast(self):
     np.random.seed(1234)
     c = np.array([[1, 4], [2, 5], [3, 6]], dtype=float)
     x = np.array([0, 0.5, 1])
     p = PPoly.construct_fast(c, x)
     assert_allclose(p(0.3), 1 * 0.3**2 + 2 * 0.3 + 3)
     assert_allclose(p(0.7), 4 * (0.7 - 0.5)**2 + 5 * (0.7 - 0.5) + 6)
Ejemplo n.º 2
0
 def test_construct_fast(self):
     np.random.seed(1234)
     c = np.array([[1, 4], [2, 5], [3, 6]], dtype=float)
     x = np.array([0, 0.5, 1])
     p = PPoly.construct_fast(c, x)
     assert_allclose(p(0.3), 1*0.3**2 + 2*0.3 + 3)
     assert_allclose(p(0.7), 4*(0.7-0.5)**2 + 5*(0.7-0.5) + 6)
Ejemplo n.º 3
0
def cdf_approx(X):  #, smoothness_factor=1):
    """
    Generates a ppoly spline to approximate the cdf of a random variable,
    from a 1-D array of i.i.d. samples thereof.

    Args:
        X: a collection of i.i.d. samples from a random variable.
        args, kwargs: any options to forward to the cvxopt qp solver
    Returns:
        scipy.interpolate.PPoly object, estimating the cdf of the random variable.
    Raises:
        TODO
    """
    # Pre-format input as ordered numpy array
    X = np.asarray(X)
    diff_X = np.diff(X)
    if not (diff_X > 0).all():
        X.sort()
        diff_X = np.diff(X)
    assert (diff_X.all())  # avoids case of duplicate X-values
    n = len(X)

    scale_axi, scale_ei = make_obj_scale(X)  #, smoothness_factor)

    P, q = make_P_q(X, scale_a=scale_axi, scale_e=scale_ei)
    G, h = make_G_h(X)
    #A, b = make_A_b(X) # simply unnecessary
    bmid_c_init = bmid_c_init_state(X)

    qp_res = cvxopt.solvers.qp(
        cvxopt.matrix(P),
        cvxopt.matrix(q),
        cvxopt.matrix(G),
        cvxopt.matrix(h),
        #cvxopt.matrix(A),
        #cvxopt.matrix(b),
        #*args, **kwargs
    )

    X, P_X, dP_X, d2P_X = clean_optimizer_results(np.array(qp_res['x']), X)

    return PPoly.construct_fast(np.stack((d2P_X, dP_X, P_X)),
                                X,
                                extrapolate=True)
Ejemplo n.º 4
0
def synth_from_pp(breaks, order, coeffs, time, radius, theta, phi, *,
                  nmax=None, source=None, deriv=None, grid=None):
    """
    Compute radial, colatitude and azimuthal field components from the magnetic
    potential in terms of a spherical harmonic expansion in form of a
    piecewise polynomial.

    Parameters
    ----------
    breaks : ndarray, shape (m+1,)
        1-D array, containing `m+1` break points (without endpoint repeats) for
        `m` intervals.
    order : int, positive
        Order `k` of piecewise polynomials (4 = cubic).
    coeffs : ndarray, shape (k, m, nmax*(nmax+2))
        Coefficients of the piecewise polynomials, where `m` is the number of
        polynomial pieces. The trailing dimension is equal to the number of
        expansion coefficients for each interval.
    time : ndarray, shape (...)
        Array containing the time in days.
    radius : ndarray, shape (...) or float
        Array containing the radius in kilometers.
    theta : ndarray, shape (...) or float
        Array containing the colatitude in degrees
        :math:`[0^\\circ,180^\\circ]`.
    phi : ndarray, shape (...) or float
        Array containing the longitude in degrees.
    nmax : int, positive, optional
        Maximum degree harmonic expansion (default is given by ``coeffs``,
        but can also be smaller, if specified).
    source : {'internal', 'external'}, optional
        Magnetic field source (default is an internal source).
    deriv : int, positive, optional
        Derivative to be taken (default is 0).
    grid : bool, optional
        If ``True``, field components are computed on a regular grid. Arrays
        ``theta`` and ``phi`` must have one dimension less than the output grid
        since the grid will be created as their outer product.

    Returns
    -------
    B_radius, B_theta, B_phi : ndarray, shape (...)
        Radial, colatitude and azimuthal field components.

    See Also
    --------
    synth_values

    """

    # handle optional argument: nmax
    nmax_coeffs = int(np.sqrt(coeffs.shape[-1] + 1) - 1)  # degree for coeffs
    if nmax is None:
        nmax = nmax_coeffs
    elif nmax > nmax_coeffs:
        warnings.warn('Supplied nmax = {0} is incompatible with number of '
                      'model coefficients. Using nmax = {1} instead.'.format(
                        nmax, nmax_coeffs))
        nmax = nmax_coeffs

    # handle optional argument: source
    source = 'internal' if source is None else source

    # compute SH coefficients from pp-form and take derivatives if needed
    deriv = 0 if deriv is None else deriv

    # set grid option to false
    grid = False if grid is None else grid

    PP = PPoly.construct_fast(coeffs[..., :nmax*(nmax+2)], breaks,
                              extrapolate=False)

    PP = PP.derivative(nu=deriv)
    gauss_coeffs = PP(time) * 365.25**deriv

    B_radius, B_theta, B_phi = synth_values(
        gauss_coeffs, radius, theta, phi, nmax=nmax, source=source, grid=grid)

    return B_radius, B_theta, B_phi
Ejemplo n.º 5
0
    def __call__(self,
                 x: Sequence[UnivariateDataType],
                 nu: Optional[Tuple[int, ...]] = None,
                 extrapolate: Optional[bool] = None) -> np.ndarray:
        """Evaluate the spline for given data

        Parameters
        ----------

        x : tuple of 1-d array-like
            The tuple of point values for each dimension to evaluate the spline at.

        nu : [*Optional*] tuple of int
            Orders of derivatives to evaluate. Each must be non-negative.

        extrapolate : [*Optional*] bool
            Whether to extrapolate to out-of-bounds points based on first and last
            intervals, or to return NaNs.

        Returns
        -------

        y : array-like
            Interpolated values. Shape is determined by replacing the
            interpolation axis in the original array with the shape of x.

        """

        x = ndgrid_prepare_data_vectors(x, 'x', min_size=1)

        if len(x) != self.ndim:
            raise ValueError(
                f"'x' sequence must have length {self.ndim} according to 'breaks'")

        if nu is None:
            nu = (0,) * len(x)

        if extrapolate is None:
            extrapolate = True

        shape = tuple(x.size for x in x)

        coeffs = ndg_coeffs_to_flatten(self.coeffs)
        coeffs_shape = coeffs.shape

        ndim_m1 = self.ndim - 1
        permuted_axes = (ndim_m1, *range(ndim_m1))

        for i in reversed(range(self.ndim)):
            umv_ndim = prod(coeffs_shape[:ndim_m1])
            c_shape = (umv_ndim, self.pieces[i] * self.order[i])
            if c_shape != coeffs_shape:
                coeffs = coeffs.reshape(c_shape)

            coeffs_cnl = umv_coeffs_to_canonical(coeffs, self.pieces[i])

            spline = PPoly.construct_fast(coeffs_cnl, self.breaks[i], axis=1)
            coeffs = spline(x[i], nu=nu[i], extrapolate=extrapolate)

            shape_r = (*coeffs_shape[:ndim_m1], shape[i])
            coeffs = coeffs.reshape(shape_r).transpose(permuted_axes)
            coeffs_shape = coeffs.shape

        return coeffs.reshape(shape)