예제 #1
0
def smooth_vel(wave, spec, outwave, sigma, nsigma=10, inres=0, **extras):
    """Smooth a spectrum in velocity space.  This is insanely slow, but general
    and correct.
    :param wave:
        Wavelength vector of the input spectrum.
    :param spec:
        Flux vector of the input spectrum.
    :param outwave:
        Desired output wavelength vector.
    :param sigma:
        Desired velocity resolution (km/s), *not* FWHM.
    :param nsigma:
        Number of sigma away from the output wavelength to consider in the
        integral.  If less than zero, all wavelengths are used.  Setting this
        to some positive number decreses the scaling constant in the O(N_out *
        N_in) algorithm used here.
    :param inres:
        The velocity resolution of the input spectrum (km/s), *not* FWHM.
    """
    sigma_eff_sq = sigma**2 - inres**2
    # if np.any(sigma_eff_sq) < 0.0:
    #     raise ValueError("Desired velocity resolution smaller than the value"
    #                      "possible for this input spectrum.".format(inres))
    # sigma_eff is in units of sigma_lambda / lambda
    sigma_eff = np.sqrt(sigma_eff_sq) / ckms

    lnwave = np.log(wave)
    flux = np.zeros(len(outwave))
    for i, w in enumerate(outwave):
        x = (np.log(w) - lnwave) / sigma_eff
        # if nsigma > 0:
        good = np.abs(x) < nsigma
        x = x[good]
        _spec = spec[good]
        # else:
        #     _spec = spec
        f = np.exp(-0.5 * x**2)
        flux[i] = np.trapz(f * _spec, x) / np.trapz(f, x)
    return flux
예제 #2
0
        def fitness(z):

            # translate decision vector
            states, controls, T = unflatten(z)

            # time grid
            n = states.shape[0]
            times = np.linspace(0, T, n)

            # objective
            L = vmap(lambda state, control: self.lagrangian(
                state, control, homotopy, *params))
            L = L(states, controls)
            J = np.trapz(L, dx=T / (n - 1))

            # Lagrangian state dynamics constraints, and boundary constraints
            # e0 = self.collocate_lagrangian(states, controls, times, costs, homotopy, *params)
            e1 = self.collocate_state(states, controls, times, *params)
            e2, e3 = boundaries(states[0, :], states[-1, :])
            e = np.hstack((e1.flatten(), e2, e3))**2

            # fitness vector
            return np.hstack((J, e))
예제 #3
0
def trapz(y, x=None, dx=1.0, axis: int = -1):
  if isinstance(y, JaxArray): y = y.value
  if isinstance(x, JaxArray): x = x.value
  return jnp.trapz(y, x=x, dx=dx, axis=axis)
예제 #4
0
    def posterior(
        self,
        inputs: pd.DataFrame,
        column: str,
        grid: np.ndarray,
        batch_size: int = None,
    ) -> np.ndarray:
        """Calculates posterior distributions for the provided column.

        Calculates the conditional posterior distribution, assuming the
        data values in the other columns of the DataFrame.

        Parameters
        ----------
        inputs : pd.DataFrame
            Data on which the posterior distributions are conditioned.
            Must have columns matching self.data_columns, *except*
            for the column specified for the posterior (see below).
        column : str
            Name of the column for which the posterior distribution
            is calculated. Must be one of the columns in self.data_columns.
            However, whether or not this column is one of the columns in
            `inputs` is irrelevant.
        grid : np.ndarray
            Grid on which to calculate the posterior.
        batch_size : int, default=None
            Size of batches in which to calculate posteriors. If None, all
            posteriors are calculated simultaneously. Simultaneous calculation
            is faster, but memory intensive for large data sets.

        Returns
        -------
        np.ndarray
            Device array of shape (inputs.shape[0], grid.size).
        """

        # get the index of the provided column, and remove it from the list
        columns = list(self.data_columns)
        idx = columns.index(column)
        columns.remove(column)

        nrows = inputs.shape[0]
        batch_size = nrows if batch_size is None else batch_size

        # convert data (sans the provided column)
        # to an array with columns ordered
        X = np.array(inputs[columns].values)

        pdfs = np.zeros((nrows, len(grid)))

        for batch_idx in range(0, nrows, batch_size):

            batch = X[batch_idx:batch_idx + batch_size]

            # make a new copy of each row for each value of the column
            # for which we are calculating the posterior
            batch = np.hstack((
                np.repeat(
                    batch[:, :idx],
                    len(grid),
                    axis=0,
                ),
                np.tile(grid, len(batch))[:, None],
                np.repeat(
                    batch[:, idx:],
                    len(grid),
                    axis=0,
                ),
            ))

            # calculate probability densities
            log_prob = self._log_prob(batch).reshape((-1, len(grid)))
            pdfs = ops.index_update(
                pdfs,
                ops.index[batch_idx:batch_idx + batch_size, :],
                np.exp(log_prob),
                indices_are_sorted=True,
                unique_indices=True,
            )

        # reshape so that each row is a posterior
        pdfs = pdfs.reshape((nrows, len(grid)))
        # normalize so they integrate to one
        pdfs = pdfs / np.trapz(y=pdfs, x=grid).reshape(-1, 1)
        # set NaN's equal to zero probability
        pdfs = np.nan_to_num(pdfs, nan=0.0)
        return pdfs
예제 #5
0
def smooth_wave(wave,
                spec,
                outwave,
                sigma,
                nsigma=10,
                inres=0,
                in_vel=False,
                **extras):
    """Smooth a spectrum in wavelength space.  This is insanely slow, but
    general and correct (except for the treatment of the input resolution if it
    is velocity)
    :param wave:
        Wavelength vector of the input spectrum.
    :param spec:
        Flux vector of the input spectrum.
    :param outwave:
        Desired output wavelength vector.
    :param sigma:
        Desired resolution (*not* FWHM) in wavelength units.  This can be a
        vector of same length as ``wave``, in which case a wavelength dependent
        broadening is calculated
    :param nsigma: (optional, default=10)
        Number of sigma away from the output wavelength to consider in the
        integral.  If less than zero, all wavelengths are used.  Setting this
        to some positive number decreses the scaling constant in the O(N_out *
        N_in) algorithm used here.
    :param inres: (optional, default: 0.0)
        Resolution of the input, in either wavelength units or
        lambda/dlambda (c/v).  Ignored if <= 0.
    :param in_vel: (optional, default: False)
        If True, the input spectrum has been smoothed in velocity
        space, and ``inres`` is assumed to be in lambda/dlambda.
    :returns flux:
        The output smoothed flux vector, same length as ``outwave``.
    """
    # sigma_eff is in angstroms
    if inres <= 0:
        sigma_eff_sq = sigma**2
    elif in_vel:
        # Make an approximate correction for the intrinsic wavelength
        # dependent dispersion.  This sort of maybe works.
        sigma_eff_sq = sigma**2 - (wave / inres)**2
    else:
        sigma_eff_sq = sigma**2 - inres**2
    if np.any(sigma_eff_sq < 0):
        raise ValueError("Desired wavelength sigma is lower than the value "
                         "possible for this input spectrum.")

    sigma_eff = np.sqrt(sigma_eff_sq)
    flux = np.zeros(len(outwave))
    for i, w in enumerate(outwave):
        x = (wave - w) / sigma_eff
        if nsigma > 0:
            good = np.abs(x) < nsigma
            x = x[good]
            _spec = spec[good]
        else:
            _spec = spec
        f = np.exp(-0.5 * x**2)
        flux[i] = np.trapz(f * _spec, x) / np.trapz(f, x)
    return flux