A Python package for static and dynamic rotor balancing calculations based on the methodology described in “Static and Dynamic Balancing using portable measuring equipment” by John Vaughan (Brüel & Kjær Application Note).
Features
VibrationVector: Represents unbalance by means of a vector
MassVector: Represents a mass placed at an angular position on a rotor
StaticBalancing: Single-plane balancing for rotors
DynamicBalancing: Two-plane balancing for rotors
VibrationExtractor: Extracts vibration vectors from time-domain signals
detect_rotation_freq: Detects rotation frequency from a trigger signal
Four pluggable extraction methods: IQDemodulation (default), LeastSquaresFit, SynchronousAveraging, FFTExtraction
Installation
Install from PyPI:
pip install pyPRB
Or install from source:
git clone https://github.com/ladisk/pyPRB.git
cd pyPRB
pip install .
For development installation:
pip install -e .[dev]
Quick Start
Static Balancing Example
from pyPRB import VibrationVector, MassVector, StaticBalancing
# Initial measurements
V_0 = VibrationVector(amplitude=3.4, phase=116) # No trial mass
V_1 = VibrationVector(amplitude=1.8, phase=42) # With trial mass
# Trial mass: 2.0 g mounted at 0° on the rotor
trial_mass = MassVector(2.0, 0.0)
# Create balancer
balancer = StaticBalancing(V_0, V_1, trial_mass=trial_mass)
# Display measurement table
print(balancer)
# Compute compensation
comp_mass = balancer.compute_compensation()
# Output: Compensation mass: 2.01 g at position -30.8° on the rotor.
Dynamic Balancing Example
from pyPRB import VibrationVector, MassVector, DynamicBalancing
# Initial measurements (no trial masses)
V_1_0 = VibrationVector(7.2, 238) # Plane 1
V_2_0 = VibrationVector(13.5, 296) # Plane 2
# With trial mass in Plane 1
V_1_1 = VibrationVector(4.9, 114) # Plane 1
V_2_1 = VibrationVector(9.2, 347) # Plane 2
# With trial mass in Plane 2
V_1_2 = VibrationVector(4.0, 79) # Plane 1
V_2_2 = VibrationVector(12.0, 292) # Plane 2
# Trial masses: 2.5 g each, mounted at 0° on their respective planes
trial_mass_1 = MassVector(2.5, 0.0)
trial_mass_2 = MassVector(2.5, 0.0)
# Create balancer
balancer = DynamicBalancing(
V_1_0, V_2_0, V_1_1, V_2_1, V_1_2, V_2_2,
trial_mass_1=trial_mass_1, trial_mass_2=trial_mass_2
)
# Display measurement table
print(balancer)
# Compute compensations for both planes
comp_mass_1, comp_mass_2 = balancer.compute_compensation()
# Output:
# +---------+---------------------+------------+
# | Plane | Compensation Mass | Position |
# +=========+=====================+============+
# | 1 | 2.95 g | 50.2° |
# +---------+---------------------+------------+
# | 2 | 2.84 g | -81.9° |
# +---------+---------------------+------------+
Extracting Vibration Vectors from Measurements
import numpy as np
from pyPRB import (
VibrationExtractor, detect_rotation_freq,
MassVector, StaticBalancing,
)
# Synthetic signals (B&K Example 2)
sample_rate = 10000 # Hz
f0_true = 25.0 # rotation frequency (Hz)
duration = 5.0 # s
t = np.arange(0, duration, 1 / sample_rate)
rng = np.random.default_rng(0)
trigger = np.sign(np.sin(2 * np.pi * f0_true * t))
signal_run0 = (3.4 * np.cos(2 * np.pi * f0_true * t + np.deg2rad(116))
+ 0.05 * rng.standard_normal(len(t)))
signal_run1 = (1.8 * np.cos(2 * np.pi * f0_true * t + np.deg2rad(42))
+ 0.05 * rng.standard_normal(len(t)))
# 1. Detect rotation frequency from the trigger signal
f0 = detect_rotation_freq(trigger, sample_rate=sample_rate, max_freq=50.0)
# 2. Create extractor (default method: IQ demodulation)
extractor = VibrationExtractor(sample_rate=sample_rate, rotation_freq=f0)
# 3. Extract vibration vectors for each measurement run
V_0 = extractor.get_vibration_vector(signal_run0, trigger)
V_1 = extractor.get_vibration_vector(signal_run1, trigger)
# 4. Use the vectors for balancing
trial_mass = MassVector(2.0, 0.0)
balancer = StaticBalancing(V_0, V_1, trial_mass=trial_mass)
comp_mass = balancer.compute_compensation()
# Output: Compensation mass: 2.01 g at position -30.8° on the rotor.
Balancing procedure
Static Balancing
For a rotor with unbalance in a single plane:
Measure initial vibration vector V₀
Add known trial mass m and measure resulting vibration V₁
Compute compensation mass with StaticBalancing
Dynamic Balancing
For a rotor requiring two-plane balancing:
Measure initial vibration vectors in both planes: V₁,₀ and V₂,₀
Add trial mass m₁,₁ in plane 1, measure: V₁,₁ and V₂,₁
Add trial mass m₂,₂ in plane 2, measure: V₁,₂ and V₂,₂
Compute compensation masses in both planes with DynamicBalancing
Metadata
Release files for pyPRB 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pyprb-1.0.0.tar.gz | 19.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pyprb-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 44.2 kB
Release files / pyprb-1.0.0.tar.gz
| Download URL | pyprb-1.0.0.tar.gz |
|---|---|
| Size | 19.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
70df984586e7302948a072c55cce359c2eeaab5871294015be86aaecd318e6d7
|
|
BLAKE2b-256 checksum How to use checksums |
c1880e5093a4afc191483fb700f5d1c504b2de885f9ab8e75c68769ec01289d2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.8
|
Release files / pyprb-1.0.0-py3-none-any.whl
| Download URL | pyprb-1.0.0-py3-none-any.whl |
|---|---|
| Size | 25.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d1ab42489c2f400a30661d0c0f732d3a7d39585ba44f02e71b6f9cbe549be34c
|
|
BLAKE2b-256 checksum How to use checksums |
7840370393bc13cb3fbfa3b1175aa5fe36eaf10c60dd4da909c5339981f0f9c7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.8
|