Metadata-Version: 2.4
Name: powerbin
Version: 1.0.6
Summary: PowerBin: Fast Adaptive Data Binning with Centroidal Power Diagrams
Home-page: https://pypi.org/project/powerbin/
Author: Michele Cappellari
Author-email: michele.cappellari@physics.ox.ac.uk
License: Other/Proprietary License
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Description-Content-Type: text/x-rst
Requires-Dist: plotbin
Requires-Dist: numpy
Requires-Dist: scipy
Requires-Dist: matplotlib
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: license
Dynamic: requires-dist
Dynamic: summary

The PowerBin Package
====================

**PowerBin: Fast Adaptive Data Binning with Centroidal Power Diagrams**

.. image:: https://users.physics.ox.ac.uk/~cappellari/images/powerbin-logo.svg
    :target: https://users.physics.ox.ac.uk/~cappellari/software/#sec:powerbin
    :width: 100
.. image:: https://img.shields.io/pypi/v/powerbin.svg
    :target: https://pypi.org/project/powerbin/
.. image:: https://img.shields.io/badge/arXiv-2509.06903-orange.svg
    :target: https://arxiv.org/abs/2509.06903
.. image:: https://img.shields.io/badge/DOI-10.48550/arXiv.2509.06903-green.svg
    :target: https://doi.org/10.48550/arXiv.2509.06903
    
This `PowerBin` package provides a Python implementation of the **PowerBin** algorithm — a modern alternative to the classic Voronoi binning method. Like Voronoi binning, it performs 2D adaptive spatial binning to achieve a nearly constant value per bin of a chosen *capacity* (e.g., signal‑to‑noise ratio or any other user‑defined function of the bin spaxels).

**Key advances over the classic method include:**

-   **Centroidal Power Diagram:** Produces bins that are nearly round, convex, and connected, and eliminates the disconnected or nested bins that could occur with earlier approaches.

-   **Scalability:** The entire algorithm scales with **O(N log N)** complexity, removing the **O(N^2)** bottleneck previously present in both the bin-accretion and regularization steps. This makes processing million‑pixel datasets practical.

-   **Stable CPD construction:** Generates the tessellation via a heuristic inspired by packed soap bubbles, avoiding the numerical fragility of formal CPD solvers with realistic non-additive capacities (e.g., correlated noise).

The algorithm combines a fast initial bin-accretion phase with iterative regularization, and is described in detail in `Cappellari (2025) <https://arxiv.org/abs/2509.06903>`_.

.. contents:: :depth: 2

Attribution
-----------

If you use this software for your research, please cite `Cappellari (2025)`_.
The BibTeX entry for the paper is::

    @ARTICLE{Cappellari2025,
        author = {{Cappellari}, M.},
        title = "{PowerBin: Fast adaptive data binning with Centroidal Power Diagrams}",
        journal = {MNRAS},
        eprint = {2509.06903},
        year = 2025,
        note = {submitted}
    }

Installation
------------

install with::

    pip install powerbin

Without write access to the global ``site-packages`` directory, use::

    pip install --user powerbin

To upgrade ``PowerBin`` to the latest version use::

    pip install --upgrade powerbin

Usage Examples
--------------

To learn how to use the ``PowerBin`` package, copy, modify and run
the example programs in the ``powerbin/examples`` directory.
It can be found within the main ``powerbin`` package installation folder
inside `site-packages <https://stackoverflow.com/a/46071447>`_.
The detailed documentation is contained in the docstring of the file
``powerbin/core.py``, or on `PyPi <https://pypi.org/project/powerbin/>`_.

Minimal example
---------------

Below is a minimal usage example you can copy into a script (or run the
provided example in ``powerbin/examples/example.py``).

In this example, the bin capacity function is defined as ``(S/N)^2``. This is a
convenient choice for illustration because, in the Poissonian limit,
``(S/N)^2`` equals the total signal, which is an additive quantity. This setup
lets us compare the behaviour of binning with an additive capacity versus a
non‑additive one. PowerBin does not require the capacity to be additive — you
can verify this in the example by setting ``covariance = True``.

.. code-block:: python

    from importlib import resources
    import numpy as np
    import matplotlib.pyplot as plt
    from powerbin import PowerBin

    data_path = resources.files('powerbin') / 'examples/sample_data_ngc2273.txt'
    x, y, signal, noise = np.loadtxt(data_path).T
    xy = np.column_stack([x, y])

    target_sn = 50

    # Set covariance = True to simulate correlated noise
    covariance = False

    def fun_capacity(index):
        """Return (S/N)^2, which is additive in the Poissonian case."""
        sn = np.sum(signal[index]) / np.sqrt(np.sum(noise[index]**2))
        if covariance:
            sn /= 1 + 1.07 * np.log10(len(index))
        return sn**2

    # Here target capacity = target_sn^2, consistent with our choice of capacity definition
    pow = PowerBin(xy, fun_capacity, target_sn**2, verbose=1)

    # PowerBin reports the fractional RMS of the bin capacity (here, (S/N)^2).
    # To obtain the fractional scatter in S/N itself, take the square root of the capacity values.
    # (By error propagation, dividing the capacity scatter by 2 gives the same result.)
    sn_bin = np.sqrt(pow.capacity[~pow.single])
    rms_frac = np.std(sn_bin, ddof=1) / np.mean(sn_bin) * 100
    print(f'Fractional S/N Scatter: {rms_frac:.1f} %')

    # The binning was performed on (S/N)^2, but for plotting we want S/N.
    # Apply a square-root scaling to the capacity before plotting.
    pow.plot(capacity_scale='sqrt', ylabel='S/N')
    plt.pause(5)

###########################################################################

PowerBin Class
==============

PowerBin Purpose
----------------

Performs 2D adaptive spatial binning to achieve a target capacity per bin.

This class implements the **PowerBin** algorithm described in
`Cappellari (2025) <https://arxiv.org/abs/2509.06903>`_. Like the classic
Voronoi binning method, it partitions a set of 2D points (pixels) into bins
so that each bin reaches a nearly constant *capacity* — a user‑defined
quantity such as signal‑to‑noise squared.

**Key advances over the classic method include:**

- **Centroidal Power Diagram:** Produces bins that are nearly round,
  convex, and connected, and eliminates the disconnected or nested bins
  that could occur with earlier approaches.

- **Scalability:** Employs new bin-accretion and iterative regularization
  algorithms with **O(N log N)** time complexity, removing the **O(N^2)**
  bottleneck of the original method and making million-pixel datasets
  practical.

- **Stable CPD construction:** Uses a heuristic inspired by packed soap
  bubbles, avoiding the numerical fragility of formal CPD solvers with
  realistic non-additive capacities (e.g., correlated noise).

The algorithm proceeds in two main stages:

1. **Initial bin-accretion** to generate starting bin centers.
2. **Iterative regularization** that adjusts bin shapes using the CPD to
   better equalize bin capacities.

Parameters
----------

xy: ndarray of shape (npix, 2)
    Coordinates of the pixels to be binned.
fun_capacity: callable
    Function to compute the capacity of a set of pixels. It must have the
    signature `fun_capacity(indices, *args)`, where `indices` is an array
    of integer indices into the original `xy` array, and `*args` are
    any additional arguments passed via the `args` parameter. The function
    should return a single float value representing the capacity.
target_capacity: float
    The target capacity for each bin.
pixelsize: float, optional
    The size of a pixel in the input coordinate units. This is used to
    internally work in pixel units, which is more numerically stable.
    If None, it is estimated as the median distance to the second‑nearest
    neighbor using a KDTree.
verbose: int, optional
    Controls the level of printed output.
    - 0: No output.
    - 1: Basic summary information (default).
    - 2: Detailed iteration-by-iteration printed progress.
    - 3: Same as 2, but also plots the binning at each iteration (slow).
regul: bool, optional
    If True (default), perform the iterative regularization step after the
    initial accretion. If False, only the initial accretion is performed.
args: tuple, optional
    Additional positional arguments to be passed to `fun_capacity`.
maxiter: int, optional
    Maximum number of iterations for the regularization step (default: 50).

Attributes
----------

xy: ndarray of shape (npix, 2)
    The original input pixel coordinates.
dens: ndarray of shape (npix,)
    The input capacity density of every pixel.
bin_num: ndarray of int of shape (npix,)
    A one‑dimensional array with one entry per element of `xy`, where each
    entry gives the index of the bin containing that pixel. This bin-index
    array is the principal output and is sufficient for any further
    processing of the bins.
fun_capacity: callable
    The function used to compute bin capacity.
target_capacity: float
    The target capacity value for the bins.
pixelsize: float
    The pixel size used for scaling (all internal computations use pixel units).
verbose: int
    The verbosity level.
args: tuple
    Additional arguments for `fun_capacity`.
single: ndarray of bool of shape (nbin,)
    Boolean array indicating which bins contain just one pixel.
xybin: ndarray of shape (nbin, 2)
    The coordinates of the Power Diagram generators (bin centers), in the
    same units as the input `xy`.
rbin: ndarray of shape (nbin,)
    The radii of the Power Diagram generators, in the same units as the
    input `xy`.
capacity: ndarray of shape (nbin,)
    The final calculated capacity for each bin.
npix: ndarray of int of shape (nbin,)
    The number of pixels in each bin.
rms_frac: float
    The fractional root-mean-square scatter of the bin capacities,
    calculated for non-single bins, as a percentage.

References
----------

.. [1] Cappellari, M. 2025, MNRAS submitted, https://arxiv.org/abs/2509.06903

###########################################################################


License
=======

Copyright (C) 2025 Michele Cappellari  
E-mail: michele.cappellari_at_physics.ox.ac.uk  

Updated versions of this software are available at:  
https://pypi.org/project/powerbin/  

If you use this software in published research, please acknowledge it as:  
“PowerBin method by Cappellari (2025, MNRAS submitted)”  
https://arxiv.org/abs/2509.06903  

This software is provided “as is”, without any warranty of any kind,  
express or implied.  

Permission is granted for:  
 - Non-commercial use.  
 - Modification for personal or internal use, provided that this  
   copyright notice and disclaimer remain intact and unaltered  
   at the beginning of the file.  

All other rights are reserved. Redistribution of the code, in whole or in part,  
is strictly prohibited without prior written permission from the author.

###########################################################################


Changelog
---------

V1.0.6: Oxford, 17 September 2025
+++++++++++++++++++++++++++++++++

- Created by Michele Cappellari.

