Skip to main content

Fluxed

PyPI Version License: GPL v3 Build Status

Fluxed is a Python package for defining N-dimensional shapes and computing the flux of arbitrary intensity distributions through them. It features a powerful tool to numerically find distribution parameters that match a desired flux value, enabling comparisons across different geometries and distributions.

Built on numpy and scipy, Fluxed provides an intuitive, array-based interface for complex spatial analysis.

Key Features

  • N-Dimensional Shapes: Define complex shapes and borders in any number of dimensions using simple NumPy arrays.
  • Automated Boundary Detection: Automatically determines if a shape's border is closed and encloses a valid region for flux calculation.
  • Flux Computation: Calculates the integrated flux (sum of intensity) within a closed shape for any given intensity distribution.
  • Rich Distribution Library: Comes with common distributions like Normal, Uniform, Linear, and Exponential in 1D and 2D.
  • Custom Distributions: Easily extend the framework with your own custom, callable distribution functions.
  • Flux Matching: The core feature—numerically optimize the parameters of a target distribution to match the flux of a source shape. This is perfect for modeling, simulation, and comparative analysis.

Installation

Fluxed is available on PyPI. You can install it using pip:

pip install Fluxed

You can also install the latest version from GitHub:

pip install git+https://github.com/CrazeXD/Fluxed.git

The package requires numpy and scipy, which will be installed automatically as dependencies.

Core Concepts

1. NdShape

An NdShape object represents a shape in N-dimensional space. You create it from a NumPy array where 1s define the border and 0s represent empty space. The class can automatically determine if the border is is_closed and can calculate the flux within this enclosed region.

2. Distribution

A Distribution is a callable object that returns an intensity value for a given coordinate. The library provides several ready-to-use distributions (e.g., NormalDistribution2D), and you can easily create your own by inheriting from the Distribution base class.

3. Flux

In the context of this package, "flux" is the sum of all intensity values from a Distribution over the discrete points inside the enclosed region of an NdShape. It's a discrete integral of the intensity over the shape's area or volume.

Quickstart

Let's walk through a complete example, from calculating a simple flux to using the advanced flux-matching feature.

Step 1: Define a Shape

First, let's create a simple 2D shape: a 3x3 hollow square within a 5x5 grid.

import numpy as np
from Fluxed.shapes import NdShape

# 1s are the border, 0s are the interior/exterior
border_array = np.array([
    [1, 1, 1, 1, 1],
    [1, 0, 0, 0, 1],
    [1, 0, 0, 0, 1],
    [1, 0, 0, 0, 1],
    [1, 1, 1, 1, 1],
], dtype=int)

my_shape = NdShape(border_array)

print(f"Shape is {my_shape.dimensions}D")
print(f"Is the shape closed? {my_shape.is_closed}")

# > Shape is 2D
# > Is the shape closed? True

Step 2: Calculate a Simple Flux

Now, let's calculate the flux using a UniformDistribution. With a value of 1.0, the flux will be equal to the enclosed area.

from Fluxed.distributions import UniformDistribution

# Create a distribution where the intensity is 1.0 everywhere
uniform_dist = UniformDistribution(value=1.0)

# Calculate the flux
total_flux = my_shape.get_flux(uniform_dist)

# The enclosed area is 3x3 = 9. The flux should be 9.0.
print(f"Total flux for uniform distribution: {total_flux}")

# > Total flux for uniform distribution: 9.0

Step 3: Match Flux with a Different Distribution

This is where Fluxed shines. Let's say we have a source of energy that produces a total flux of 90.0. We want to model this energy source on our shape using a NormalDistribution2D (a Gaussian). What should the parameters of the Gaussian be (mean, stddev) to produce the same total flux?

The match_flux_parameters function solves this for us.

from Fluxed.distributions import NormalDistribution2D
from Fluxed.match import match_flux_parameters

# --- Source ---
# Our source is a uniform distribution with value 10.0
# The enclosed area is 9, so the target flux is 9 * 10.0 = 90.0
source_dist = UniformDistribution(value=10.0)

# --- Target ---
# We want to find the parameters for a NormalDistribution2D
# that will also produce a flux of 90.0 on the same shape.
TargetDistClass = NormalDistribution2D

# We want the optimizer to find the standard deviations.
# We'll fix the mean to be the center of the grid (2, 2).
# To do this, we create a simple wrapper.
class CenteredNormal(NormalDistribution2D):
    def __init__(self, stddev_x: float = 1.0, stddev_y: float = 1.0):
        # Fix the mean to the center of our 5x5 grid
        super().__init__(mean_x=2.0, mean_y=2.0, stddev_x=stddev_x, stddev_y=stddev_y)

# Parameters for the optimizer to find
params_to_find = ['stddev_x', 'stddev_y']
initial_guess = [1.0, 1.0]  # An initial guess for the standard deviations
bounds = [(0.1, None), (0.1, None)] # Stddev must be positive

# --- Run the optimizer ---
result = match_flux_parameters(
    source_shape=my_shape,
    source_dist=source_dist,
    target_shape=my_shape,
    TargetDistClass=CenteredNormal,
    param_names=params_to_find,
    initial_guess=initial_guess,
    bounds=bounds
)

# --- Analyze the result ---
if result['success']:
    print("Optimization successful!")
    print(f"Target Flux: {result['target_flux']:.4f}")
    print(f"Achieved Flux: {result['final_flux']:.4f}")
    print("Found optimal parameters:")
    for param, value in result['parameters'].items():
        print(f"  {param}: {value:.4f}")
else:
    print(f"Optimization failed: {result['message']}")

Example Output:

Calculating target flux from source shape and UniformDistribution...
Target Flux = 90.0000

Optimizing parameters ['stddev_x', 'stddev_y'] for CenteredNormal...
Optimization successful!
Target Flux: 90.0000
Achieved Flux: 90.0000
Found optimal parameters:
  stddev_x: 1.2585
  stddev_y: 1.2585

The result tells us that a 2D Normal distribution centered at (2, 2) with a standard deviation of approximately 1.26 along both axes will produce the same total flux as a uniform distribution of value 10.

Creating a Custom Distribution

It's easy to define your own distributions. Just inherit from Distribution and provide a callable function.

Let's create a 1D distribution that varies with the sine of the x-coordinate.

import numpy as np
from Fluxed.distributions import Distribution

class SineDistribution1D(Distribution):
    """A custom distribution where intensity varies sinusoidally."""
    def __init__(self, frequency: float = 1.0, amplitude: float = 1.0):
        # The function must accept arguments corresponding to the dimensions
        # of the space it will be used in.
        def sine_func(x):
            # We add `amplitude` to ensure intensity is always non-negative
            return amplitude * np.sin(frequency * x) + amplitude

        # Call the parent constructor
        super().__init__("SineDistribution1D", sine_func)
        self.frequency = frequency
        self.amplitude = amplitude

# --- Usage ---
shape_1d = NdShape(np.array([1, 0, 0, 0, 1])) # A simple 1D enclosed space
my_sine_dist = SineDistribution1D(frequency=np.pi/2, amplitude=10)

# The function will be evaluated at x=1, 2, 3
# sin(pi/2*1) = 1  -> intensity = 10*1 + 10 = 20
# sin(pi/2*2) = 0  -> intensity = 10*0 + 10 = 10
# sin(pi/2*3) = -1 -> intensity = 10*(-1) + 10 = 0
# Expected flux = 20 + 10 + 0 = 30
flux = shape_1d.get_flux(my_sine_dist)
print(f"Flux for custom sine distribution: {flux}")
# > Flux for custom sine distribution: 30.0

Running Tests

To run the test suite from a local clone of the repository, install the development dependencies and run pytest.

git clone https://github.com/CrazeXD/Fluxed.git
cd Fluxed
pip install -r requirements.txt  # Or similar for dev dependencies
pip install pytest
pytest

Contributing

Contributions are welcome! If you have ideas for new features, distributions, or improvements, please open an issue to discuss it first. Pull requests are also appreciated.

License

This project is licensed under the GNU General Public License v3.0 - see the LICENSE file for details.

Release files for Fluxed 1.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for Fluxed 1.0.1
File Size Uploaded
fluxed-1.0.1.tar.gz 29.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for Fluxed 1.0.1
File Interpreter ABI Platform
fluxed-1.0.1-py3-none-any.whl Python 3 none any Details

Total release size: 54.4 kB

Release files / fluxed-1.0.1.tar.gz

Download URL fluxed-1.0.1.tar.gz
Size 29.2 kB
Tags Source
SHA-256 checksum
How to use checksums
2c05f8b49e6a32f3cb9171e95cefe8998c7d38faa0c1138b2ad1e6320e05e127
BLAKE2b-256 checksum
How to use checksums
656f7decd614cf878952def4777d4f5244c90ca3047ecea52feee1874e8f2c7b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.12.9

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 8, 2025.

Transparency log

Release files / fluxed-1.0.1-py3-none-any.whl

Download URL fluxed-1.0.1-py3-none-any.whl
Size 25.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1e33a2f7e578dc72da7dc06bf9a49627efc4e3cdcf50282be2c3e2169503b682
BLAKE2b-256 checksum
How to use checksums
396cfc882ea718b7ac9bfba46331b88e662a352d495efe6fe08695db4f84754e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.12.9

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 8, 2025.

Transparency log

Release history Release notifications | RSS feed

This release

1.0.1 This release

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page