Progress Reporting

Both find_power() and find_sample_size() accept a progress_callback parameter that controls how progress is reported during the simulation.


Resolution Logic

The behavior of progress_callback depends on both its value and print_results:

progress_callback

print_results

Behavior

None (default)

True (default)

Auto PrintReporter() – prints progress to stderr

None

False

Silent – no progress output

callable

any

Uses the provided callback (current: int, total: int)

False

any

Explicitly disables progress

Built-in Reporters

PrintReporter

class mcpower.PrintReporter[source]

Bases: object

Console progress reporter — prints \rProgress: 45.2% (723/1600 simulations).

Console progress reporter. Writes text-based progress to stderr. This is the default when print_results=True.

from mcpower import MCPower, PrintReporter

model = MCPower("y = x1 + x2")
model.set_simulations(400)
model.set_effects("x1=0.5, x2=0.3")

# Default behavior (PrintReporter auto-selected)
model.find_power(sample_size=100)
# Output on stderr: "Progress: 45.2% (723/1600)"
# Explicit PrintReporter
model.find_power(sample_size=100, progress_callback=PrintReporter())

TqdmReporter

class mcpower.TqdmReporter(**tqdm_kwargs)[source]

Bases: object

Optional tqdm-based progress reporter (lazy import).

Usage:

from mcpower.progress import TqdmReporter
model.find_power(100, progress_callback=TqdmReporter())

Optional tqdm-based progress reporter. Requires the tqdm package.

from mcpower import MCPower, TqdmReporter

model = MCPower("y = x1 + x2")
model.set_effects("x1=0.5, x2=0.3")

model.find_power(sample_size=100, progress_callback=TqdmReporter())
# Displays: [=========>          ] 45% 723/1600

ProgressReporter

class mcpower.ProgressReporter(total, callback, update_every=None)[source]

Bases: object

Wraps a (current, total) callback with counting and throttling.

Tracks the number of completed simulation steps and fires the callback at most once every update_every advances, preventing excessive I/O when simulations complete very quickly.

Parameters:
  • total (int) – Total number of simulation steps.

  • callback (Callable[[int, int], None]) – Function called as callback(current, total) on each (throttled) update.

  • update_every (int | None) – Fire the callback at most once per this many advances. Defaults to max(1, total // 200) (~200 updates total).

start()[source]

Signal the beginning of the run (fires an initial 0/total update).

advance(n=1)[source]

Advance the counter by n steps, firing the callback when due.

Parameters:

n (int)

finish()[source]

Signal completion (fires a final total/total update if not already there).

Low-level wrapper that tracks completed simulation steps and throttles callback invocations. Typically you do not need to use this directly – it is used internally by MCPower.

SimulationCancelled

class mcpower.SimulationCancelled[source]

Bases: Exception

Raised when a simulation is cancelled by the user.

Exception raised when a simulation is cancelled via the cancel_check callback.

Custom Callbacks

Any callable that accepts (current: int, total: int) can be used as a progress callback:

from mcpower import MCPower

model = MCPower("y = x1 + x2")
model.set_simulations(400)
model.set_effects("x1=0.5, x2=0.3")

# Simple print callback
model.find_power(
    sample_size=100,
    progress_callback=lambda cur, tot: print(f"{cur}/{tot}"),
)
# Percentage callback
def show_percent(current, total):
    pct = current / total * 100
    print(f"\r{pct:.1f}% complete", end="", flush=True)

model.find_power(sample_size=100, progress_callback=show_percent)

GUI Integration

For GUI applications, the callback bridges simulation progress to UI updates:

# PySide6 / PyQt example
def on_progress(current, total):
    progress_signal.emit(current, total)  # Emit Qt signal to update progress bar

model.find_power(
    sample_size=100,
    print_results=False,
    progress_callback=on_progress,
)

Disabling Progress

# Explicitly disable (even when print_results=True)
model.find_power(sample_size=100, progress_callback=False)
# Implicitly disabled (no print_results, no explicit callback)
model.find_power(sample_size=100, print_results=False)

Total Simulation Count

The total value passed to callbacks reflects the total number of simulation iterations across all scenarios and sample sizes:

Analysis

Total

find_power(N)

n_simulations

find_power(N, scenarios=True)

n_simulations * 3 (optimistic + realistic + doomer)

find_sample_size(from, to, by)

n_simulations * n_sample_sizes

find_sample_size(..., scenarios=True)

n_simulations * n_sample_sizes * 3

Throttling

The built-in ProgressReporter wrapper throttles updates to approximately 200 calls maximum (update_every = max(1, total // 200)), avoiding excessive I/O overhead on fast simulations.

See Also