Overall Equipment Effectiveness for Python: availability, performance and quality with the full time waterfall, TEEP, and correct multi-machine roll-up. Computed from the standard definitions and validated against published examples.
Project description
oee
Overall Equipment Effectiveness for Python.
Compute OEE (Availability x Performance x Quality) from machine times and piece counts, get the full time waterfall and the three loss categories, TEEP and utilization, and roll figures up correctly across machines and shifts. Computed from the standard definitions and validated against published worked examples.
Motivation
OEE is the standard manufacturing efficiency metric, but Python has no library for it: what exists is monitoring applications (Flask/Django dashboards) or one-off tutorial scripts. The arithmetic looks trivial (three numbers multiplied) and that is exactly why it is usually done wrong:
- the time waterfall (planned -> run -> net run -> fully productive) and where each loss sits is skipped;
- TEEP and utilization (which capture schedule loss) are left out;
- and figures are averaged across machines, which is incorrect: a fast machine and a slow one do not combine to the mean of their OEEs.
oee does these properly, from the standard definitions, and returns one result
with the factors, the waterfall, every loss, and provenance.
pip install oee
No runtime dependencies.
Usage
The canonical worked example (Vorne's Fast Guide to OEE):
import oee
r = oee.oee(
planned_production_time=420, # minutes (480 shift - 60 of breaks)
downtime=47,
ideal_rate=60, # pieces per minute
total_count=19271,
reject_count=423,
all_time=480, # optional, for TEEP and utilization
)
r.availability # 0.888
r.performance # 0.861
r.quality # 0.978
r.oee # 0.748
r.teep # 0.654
print(r.summary())
Roll up across machines (correctly, not by averaging):
m1 = oee.oee(planned_production_time=100, run_time=90, ideal_cycle_time=1,
total_count=80, good_count=80) # OEE 0.80
m2 = oee.oee(planned_production_time=300, run_time=150, ideal_cycle_time=1,
total_count=150, good_count=135) # OEE 0.45
line = oee.aggregate([m1, m2])
line.oee # 0.5375, not the 0.625 average of the two
Break the losses down into the six big losses:
r = oee.oee(
planned_production_time=480, downtime=80, ideal_cycle_time=0.5,
total_count=700, reject_count=100,
setup_time=30, # of the 80 min down, 30 was setup
startup_rejects=40, # of the 100 rejects, 40 were at startup
)
r.six_losses
# {'breakdowns': 50.0, 'setup_and_adjustments': 30.0,
# 'minor_stops_and_reduced_speed': 50.0,
# 'process_defects': 30.0, 'reduced_yield': 20.0}
Rank the losses (or any downtime-reason breakdown) with a Pareto:
for e in oee.pareto(r.six_losses):
print(f"{e.label:30} {e.value:5.0f} {e.share:5.0%} cum {e.cumulative:5.0%}")
# breakdowns 50 28% cum 28%
# minor_stops_and_reduced_speed 50 28% cum 56%
# process_defects 30 17% cum 72%
# setup_and_adjustments 30 17% cum 89%
# reduced_yield 20 11% cum 100%
Or compute it from an event log of production runs and downtime events:
r = oee.from_log(
planned_production_time=420,
runs=[{"count": 19271, "good": 18848, "ideal_rate": 60}],
downtime_events=[
{"reason": "changeover", "duration": 30, "planned": True},
{"reason": "jam", "duration": 17},
],
)
r.oee # 0.748
r.downtime_reasons # {'changeover': 30, 'jam': 17} - ready for pareto()
When you already have the three factors:
oee.oee_from_factors(0.90, 0.95, 0.999).world_class # True (OEE >= 85%)
Charts come with the optional plot extra (pip install oee[plot]):
oee.waterfall(r) # the OEE time waterfall
oee.losses_pareto(r) # a Pareto of the six big losses
oee.trend(shifts, factors=True) # OEE and the factors across a sequence
Each draws onto a matplotlib Axes and returns it (ax.figure.savefig(...) to
save); matplotlib stays an optional extra, so the core has no dependencies.
Every result carries the factors, the time waterfall, the losses, world_class
and meets_target flags, summary(), and a JSON-safe to_dict() with
provenance (version, input hash, timestamp).
What it computes
| Group | Output |
|---|---|
| Factors | availability, performance, quality, OEE |
| Extended | TEEP, utilization (when total calendar time is given) |
| Waterfall | planned -> run -> net run -> fully productive time, with schedule, availability, performance and quality losses |
| Six big losses | breakdowns, setup and adjustments, minor stops and reduced speed, process defects, reduced yield |
| Pareto | rank any loss breakdown by share and cumulative share |
| Roll-up | correct aggregation across machines, lines and shifts |
| Charts | waterfall, six-big-losses Pareto and trend (optional plot extra) |
All times must be in the same unit; ideal_cycle_time is that unit per piece
(or pass ideal_rate in pieces per that unit). Performance above 100% is capped
and flagged, since it means the ideal rate or counts are off.
Beyond OEE
The same data supports the metrics that surround OEE, each in the same Result
style with provenance.
The effectiveness family. Pass the planned downtime and oee() adds OOE
(measured over operating time = planned production time + planned downtime), so
you get all three at once (TEEP <= OOE <= OEE):
r = oee.oee(planned_production_time=420, downtime=47, ideal_rate=60,
total_count=19271, reject_count=423, all_time=480, planned_downtime=33)
r.oee, r.ooe, r.teep # OEE >= OOE >= TEEP
Reliability, the maintenance driver of the availability factor:
oee.reliability(operating_time=1000, failures=5, total_repair_time=50)
# MTBF 200, MTTR 10, inherent availability 95.2%
Yield, the multi-step quality view that extends the single-step quality factor:
oee.rolled_throughput_yield([0.99, 0.98, 0.97]).rty # 0.941
Capacity, and the money behind the losses:
oee.takt_time(available_time=480, demand=240) # 2.0 per unit
oee.loss_value(r, value_per_unit=12.0) # losses as units and money
| Metric | What it adds |
|---|---|
oee() with planned_downtime |
OOE alongside OEE and TEEP |
reliability() |
MTBF, MTTR, inherent availability |
first_pass_yield(), rolled_throughput_yield() |
multi-step quality |
takt_time(), capacity() |
the pace needed to meet demand |
loss_value() |
losses in lost units and money |
Status
Version 0.1.0. Single-machine OEE, the time waterfall, TEEP/utilization, and
correct roll-up. The OEEResult contract is append-only from here.
Roadmap
| Version | Scope |
|---|---|
| 0.2 | an MCP server so an agent can compute and explain OEE |
Out of scope: data collection / machine connectivity (that is the job of an
MES or an IoT dashboard); oee is the calculation layer they can build on.
References
Definitions
OEE follows the standard definitions: Availability x Performance x Quality, the time waterfall, the six big losses, TEEP and the world-class benchmark.
- Nakajima, S. (1988). Introduction to TPM. Productivity Press. The origin of OEE and the world-class benchmark (availability >= 90%, performance >= 95%, quality >= 99.9%, OEE >= 85%).
- SEMI E79. The semiconductor industry standard for equipment efficiency and OEE.
- Vorne Industries, The Fast Guide to OEE (oee.com).
Worked examples
The validation suite checks the computation against published worked examples, each cited in its case:
| Example | OEE | Source |
|---|---|---|
| 8-hour shift (widgets) | 74.79% | Vorne, The Fast Guide to OEE (oee.com) |
| CNC machining shift | 68.52% | TeepTrak, How to Calculate OEE |
| Shift, clean numbers | 72.4% | ReliaMag, How to Calculate OEE |
| Longer-horizon run | 70.6% | ReliaMag, How to Calculate OEE |
| Packaging line | 67.5% | FIRGELLI Automations, OEE Calculator |
| World-class benchmark | 85.4% | Nakajima (1988), Introduction to TPM |
License
MIT. Written and maintained by Atakan Arikan, MSc Student at Tsinghua University and Politecnico di Milano.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file oee-0.2.0.tar.gz.
File metadata
- Download URL: oee-0.2.0.tar.gz
- Upload date:
- Size: 26.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
46218a99b79f4678ff6fb4fb6cee228827179bfc201d84666344869105c2bbe9
|
|
| MD5 |
bd0294b8a49c8c738d388b2a486c6a60
|
|
| BLAKE2b-256 |
798e23c164bd97c9996eb87849f8fc93231d251ad9ffdd284a06f255446baa17
|
Provenance
The following attestation bundles were made for oee-0.2.0.tar.gz:
Publisher:
release.yml on arikanatakan/oee
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
oee-0.2.0.tar.gz -
Subject digest:
46218a99b79f4678ff6fb4fb6cee228827179bfc201d84666344869105c2bbe9 - Sigstore transparency entry: 1837928077
- Sigstore integration time:
-
Permalink:
arikanatakan/oee@84f7857c173ead5e1bdd262c199dfe188c005ae2 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/arikanatakan
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@84f7857c173ead5e1bdd262c199dfe188c005ae2 -
Trigger Event:
release
-
Statement type:
File details
Details for the file oee-0.2.0-py3-none-any.whl.
File metadata
- Download URL: oee-0.2.0-py3-none-any.whl
- Upload date:
- Size: 22.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e50743b01e0e1f4742c443c005d20d3a0a27081fee0fcc41ae5d2c73d7435bd5
|
|
| MD5 |
6e5686cb11650dafc03dd97d76155a4b
|
|
| BLAKE2b-256 |
9e239c743c4198d80d0c53e8abffab3ab3a11c7b88a1ed02663c6bfb069c14c0
|
Provenance
The following attestation bundles were made for oee-0.2.0-py3-none-any.whl:
Publisher:
release.yml on arikanatakan/oee
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
oee-0.2.0-py3-none-any.whl -
Subject digest:
e50743b01e0e1f4742c443c005d20d3a0a27081fee0fcc41ae5d2c73d7435bd5 - Sigstore transparency entry: 1837928146
- Sigstore integration time:
-
Permalink:
arikanatakan/oee@84f7857c173ead5e1bdd262c199dfe188c005ae2 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/arikanatakan
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@84f7857c173ead5e1bdd262c199dfe188c005ae2 -
Trigger Event:
release
-
Statement type: