Ejemplo n.º 1
0
def histogram(sample, weights, binning, averaged):
    """Histogram `sample` points, weighting by `weights`, according to `binning`.

    Parameters
    ----------
    sample : list of SmartArrays

    weights : SmartArray

    binning : PISA MultiDimBinning

    averaged : bool
        If True, the histogram entries are averages of the numbers that end up
        in a given bin. This for example must be used when oscillation
        probabilities are translated, otherwise we end up with
        probability*count per bin

    """
    hist_func = histogram_gpu if TARGET == 'cuda' else histogram_np

    flat_hist = hist_func(sample, weights, binning, apply_weights=True)

    if averaged:
        flat_hist_counts = hist_func(sample,
                                     weights,
                                     binning,
                                     apply_weights=False)
        vectorizer.itruediv(flat_hist_counts, out=flat_hist)

    return flat_hist
Ejemplo n.º 2
0
def resample(weights, old_sample, old_binning, new_sample, new_binning):
    """Resample binned data with a given binning into any arbitrary
    `new_binning`

    Parameters
    ----------
    weights : SmartArray

    old_sample : list of SmartArrays

    old_binning : PISA MultiDimBinning

    new_sample : list of SmartArrays

    new_binning : PISA MultiDimBinning

    Returns
    -------
    new_hist_vals

    """
    if old_binning.names != new_binning.names:
        raise ValueError(
            f'cannot translate betwen {old_binning} and {new_binning}')

    # This is a two step process: first histogram the weights into the new binning
    # and keep the flat_hist_counts

    hist_func = histogram_gpu if TARGET == 'cuda' else histogram_np

    flat_hist = hist_func(old_sample, weights, new_binning, apply_weights=True)
    flat_hist_counts = hist_func(old_sample,
                                 weights,
                                 new_binning,
                                 apply_weights=False)
    vectorizer.itruediv(flat_hist_counts, out=flat_hist)

    # now do the inverse, a lookup of hist vals at `new_sample` points
    new_hist_vals = lookup(new_sample, weights, old_binning)

    # Now, for bin we have 1 or less counts, take the lookedup value instead:
    vectorizer.replace_where_counts_gt(
        vals=flat_hist,
        counts=flat_hist_counts,
        min_count=1,
        out=new_hist_vals,
    )

    return new_hist_vals
Ejemplo n.º 3
0
    def apply(self):
        # DO NOT USE THIS STAGE AS YOUR TEMPLATE IF YOU ARE NEW TO PISA!
        # --------------------------------------------------------------
        #
        # We are overwriting the `apply` method rather than the `apply_function` method
        # because we are manipulating the data binning in a delicate way that doesn't
        # work with automatic rebinning.

        self.data.data_specs = self.input_specs
        if self.scale_errors:
            for container in self.data:
                vectorizer.pow(
                    vals=container["errors"],
                    pwr=2,
                    out=container["variances"],
                )

        input_binvols = SmartArray(
            self.input_specs.weighted_bin_volumes(attach_units=False).ravel())
        output_binvols = SmartArray(
            self.output_specs.weighted_bin_volumes(attach_units=False).ravel())

        for container in self.data:
            self.data.data_specs = self.input_specs
            # we want these to be SmartArrays, so no `.get(WHERE)`
            weights_flat_hist = container["weights"]
            if self.scale_errors:
                vars_flat_hist = container["variances"]
            self.data.data_specs = self.output_specs
            if self.rs_mode == ResampleMode.UP:
                # The `unroll_binning` function returns the midpoints of the bins in the
                # dimension `name`.
                fine_gridpoints = [
                    SmartArray(
                        container.unroll_binning(name, self.output_specs))
                    for name in self.output_specs.names
                ]
                # We look up at which bin index of the input binning the midpoints of
                # the output binning can be found, and assign to each the content of the
                # bin of that index.
                container["weights_resampled"] = translation.lookup(
                    fine_gridpoints,
                    weights_flat_hist,
                    self.input_specs,
                )
                if self.scale_errors:
                    container["vars_resampled"] = translation.lookup(
                        fine_gridpoints,
                        vars_flat_hist,
                        self.input_specs,
                    )
                # These are the volumes of the bins we sample *from*
                origin_binvols = translation.lookup(
                    fine_gridpoints,
                    input_binvols,
                    self.input_specs,
                )
                # Finally, we scale the weights and variances by the ratio of the
                # bin volumes in place:
                vectorizer.imul(output_binvols, container["weights_resampled"])
                vectorizer.itruediv(origin_binvols,
                                    container["weights_resampled"])
                if self.scale_errors:
                    vectorizer.imul(output_binvols,
                                    container["vars_resampled"])
                    vectorizer.itruediv(origin_binvols,
                                        container["vars_resampled"])
            elif self.rs_mode == ResampleMode.DOWN:
                pass  # not yet implemented

            if self.scale_errors:
                vectorizer.sqrt(vals=container["vars_resampled"],
                                out=container["errors_resampled"])