Quantity and Quality
A lightweight Python library and CLI for reporting energy quantity together with energy quality.
Try it in your browser · Paper · Adoption cookbook · Changelog
Instead of writing:
1 MWh
write:
1 MWh, fx = 0.170
where fx is the Exergy Factor: accessible useful work potential per unit of energy.
For example:
1 MWh_th, fx = 0.170 [Th = 80 C, T0 = 20 C]
means that 1 MWh of 80 °C heat carries about:
0.170 MWh_ex
of accessible work potential relative to a 20 °C reference sink.
This framework is designed for make the full thermodynamic energy picture visible for energy analysts, engineers, consultants, researchers, software teams, and workflows that need a simple way to add energy-quality reporting to existing energy data.
It does not replace detailed exergy analysis, process simulation, ISO 50001, IPMVP, LCA, cost accounting, or engineering judgment. It adds one useful quality field to existing energy records so electricity, fuels, heat, cooling, storage, and savings can be compared more honestly.
What You Can Do With It
Use this framework to:
- calculate Exergy Factor for electricity, heat, cooling, fuels, and solar radiation
- convert ordinary energy records into quantity-plus-quality notation
- clean CSV, JSON, JSONL, Excel, DataFrame, SQL, stream, or URL records
- compare energy options using
MWh_ex,cost/MWh_ex, andCO2/MWh_ex - add auditable context such as reference sink, boundary, basis, assumptions, and warnings
- export canonical reference data for web calculators, dashboards, APIs, and reports
The package is designed to start simple: use reference defaults for screening, then replace them with site-specific values when accuracy matters.
Install
From PyPI:
python -m pip install quantity-and-quality
The installed command is quantity-quality (no "and"), and the import name is
quantity_quality.
For local development:
python -m pip install -e ".[all,dev]"
YAML scenario files require the optional scenario extra:
python -m pip install "quantity-and-quality[scenario]"
If the package is not yet published to PyPI, install directly from GitHub:
python -m pip install git+https://github.com/cdimurro/quantity-and-quality.git
The Three Main Workflows
1. Calculate One Stream
Use this when you know the energy form and want a quick quantity-plus-quality record.
quantity-quality calc thermal --quantity 1 --unit MWh_th --source-c 80 --sink-c 20
Example output:
80 C heat to 20 C sink
report: 1 MWh_th, fx = 0.17 [Th = 80 C, T0 = 20 C]
accessible exergy: 0.169899 MWh_ex
Other common calculations:
quantity-quality calc electricity --quantity 1 --unit MWh
quantity-quality calc fuel --quantity 1 --fuel "natural gas" --basis HHV
quantity-quality calc cooling --quantity 1 --unit MWh_cooling --cold-service-c 7 --ambient-sink-c 30
quantity-quality calc custom --quantity 1 --unit MWh --fx 0.73
2. Clean Existing Energy Records
Use this when you already have energy records in a file or data source.
quantity-quality clean examples/adoption_records.csv --output clean.csv
The cleaner accepts messy field names such as:
energy_kwh
supply_temp_f
fuel_type
reference_id
fx
exergy_factor
It adds:
- notation
- accessible exergy
- normalized
MWh_exwhere possible - reference context
- assumptions
- warnings
- validation issues
Example:
import quantity_quality as qq
records = qq.clean_records([
{"asset": "Grid meter", "energy_kwh": 845, "reference_id": "electricity-delivered"},
{"asset": "Kiln exhaust", "energy_kwh": 2738, "supply_temp_f": 1005.8},
{"asset": "Unknown stream", "quantity": 2.738, "unit": "kWh_th", "fx": 0.64},
])
for record in records:
print(record["full_notation"], record["missing_context"])
3. Compare Energy Options
Use this when you want to compare fuels, heat, electricity, waste heat, cooling, storage, or project scenarios.
quantity-quality compare examples/process_heat_comparison.json
Example output:
Option Energy fx MWh_ex Cost/MWh_ex CO2/MWh_ex
-------------------- ------------- ------- ------ ----------- ----------
Natural gas HHV 10000 MWh_HHV 0.93 9300 34.4086 194.624
Hydrogen HHV 10000 MWh_HHV 0.83 8300 114.458 0
Electric resistance 10000 MWh 1 10000 70 0
Recovered 500 C heat 10000 MWh_th 0.61437 6143.7 19.5322 0
Markdown and JSON reports are also available:
quantity-quality compare examples/process_heat_comparison.json --format markdown --output report.md
quantity-quality compare examples/process_heat_comparison.json --format json
Python API
import quantity_quality as qq
record = qq.thermal(1, "MWh_th", source_c=80, sink_c=20)
print(record.full_notation)
# 1 MWh_th, fx = 0.17 [Th = 80 C, T0 = 20 C]
print(record.accessible_exergy, record.accessible_exergy_unit)
# 0.169899... MWh_ex
Create a custom record:
record = qq.report(1, "MWh", fx=0.73)
print(record.notation)
# 1 MWh, fx = 0.73
Use a bundled reference example:
record = qq.lookup("heat-80c-standard", quantity=1.8)
print(record.full_notation)
# 1.8 MWh_th, fx = 0.17 [Th = 80 C, T0 = 20 C]
Compare scenario files:
result = qq.compare_scenario_file("examples/process_heat_comparison.json")
print(qq.scenario_to_markdown(result))
Core Formula
The reporting layer normalizes different energy carriers into one quality field:
accessible exergy = energy quantity * Exergy Factor
or:
X_A = E * fx
For power:
accessible exergy rate = power * Exergy Factor
or:
Xdot_A = P * fx
For heat, the default thermal Exergy Factor uses the Carnot factor:
fx = 1 - T0 / Th
Temperatures are converted to kelvin internally. Public examples use:
T0 = 20 C
unless another sink or reference condition is declared.
Fuel examples must declare their energy basis. HHV is recommended for broad public comparison because it avoids confusing fx > 1 values for common fuels. LHV is supported when explicitly labeled.
Why This Matters
One MWh of electricity, one MWh of 80 °C heat, one MWh of 40 °C heat, and one MWh of fuel are equal under first-law energy accounting.
They are not equal as useful work resources.
Examples with a 20 °C reference sink:
| Stream | Conventional Report | Quantity + Exergy Factor |
|---|---|---|
| Electricity | 1 MWh |
1 MWh, fx = 1.000 |
| Heat at 150 °C | 1 MWh_th |
1 MWh_th, fx = 0.307 |
| Heat at 80 °C | 1 MWh_th |
1 MWh_th, fx = 0.170 |
| Heat at 40 °C | 1 MWh_th |
1 MWh_th, fx = 0.064 |
| Methane, HHV basis | 1 MWh_HHV |
1 MWh_HHV, fx = 0.93 |
| Hydrogen, HHV basis | 1 MWh_HHV |
1 MWh_HHV, fx = 0.83 |
The Exergy Factor helps reveal:
- when high-grade resources are used for low-grade services
- when low-grade heat can be productively cascaded
- when heat pumps act as work-potential matching devices
- when fuels, electricity, heat, cooling, and storage are not directly comparable by MWh alone
- when savings should be reported as both avoided energy and avoided accessible exergy
Data Contract
The minimum direct record is:
{
"quantity": 1,
"unit": "MWh",
"exergy_factor": 0.73
}
For auditable records, add context:
{
"quantity": 1,
"unit": "MWh_th",
"exergy_factor": 0.170,
"source_c": 80,
"sink_c": 20,
"reference": "20 C thermal sink",
"boundary": "delivery point",
"basis": "Carnot factor"
}
Bundled reference examples can be used with reference_id:
{
"quantity": 1,
"unit": "MWh_th",
"reference_id": "heat-80c-standard"
}
The JSON Schema is packaged and available at:
data/quantity_quality_record.schema.json
CLI:
quantity-quality schema --json-schema
Python:
schema = qq.load_record_schema()
Reference Data
The package includes reference examples for:
- electricity
- mechanical work
- thermal streams
- cooling
- fuels
- solar radiation
- storage
- measurement and reporting use cases
quantity-quality list
quantity-quality list --category thermal
quantity-quality lookup heat-80c-standard
Reference data files:
data/reference_examples.json
data/reference_examples.csv
Each reference example declares:
- boundary
- basis
- source
- confidence class
- carrier
- reference condition
- structured context such as temperatures or fuel basis where relevant
Reference examples are starting assumptions, not universal constants. Use them for screening, teaching, first-pass comparison, and software integration. Replace them with site-specific values when making project decisions.
Website Data Export
The static exergyfactor.com calculator can consume reference data generated from this Python package:
quantity-quality export-web-data \
--output ../exergy-factor/data/reference_examples.json \
--js-output ../exergy-factor/data/reference_examples.js
The JavaScript bundle is synchronous and small, so the website calculator can load canonical values immediately without waiting for a runtime fetch.
This keeps the Python library and public calculator aligned around one source of truth.
Reporting Notation
Short notation
Use this when the reference convention is already known, the carrier is unambiguous, or the value is being used in a compact dashboard, invoice, spreadsheet, or chart.
1 MWh, fx = 0.73
Full notation
Use this for thermal streams, non-default references, technical reports, datasets, audits, and any case where another person needs to verify the value from the notation itself.
1 MWh_th, fx = 0.170 [Th = 80 C, T0 = 20 C]
Structured data
Use this in APIs, databases, telemetry, invoices, procurement data, and standards templates where records should be machine-readable.
{
"quantity": 1.0,
"unit": "MWh_th",
"exergy_factor": 0.170,
"source_c": 80,
"sink_c": 20,
"reference": "20 C thermal sink",
"boundary": "delivery point",
"basis": "Carnot factor"
}
The practical standard is:
quantity, fx = value
plus enough declared context to make the value interpretable.
Supply-Demand Matching
The framework becomes most useful when both supply and demand are reported with Exergy Factor.
Supply:
(P_s, fx_s)
Demand:
(P_d, fx_d)
Good match:
P_s ~= P_d
fx_s ~= fx_d
Wasteful match:
fx_s >> fx_d
This means a high-exergy source is being used for a low-exergy service.
Insufficient match:
fx_s < fx_d
This means the supply must be upgraded by a heat pump, compressor, reactor, electrolyzer, or another conversion process.
A simple mismatch index is:
Delta_fx = fx_s - fx_d
For a matched energy quantity:
X_mismatch = E_matched * max(0, fx_s - fx_d)
Stream Quality vs. Process Efficiency
The framework keeps stream reporting separate from process performance.
Stream descriptor:
(E, fx)
or:
(P, fx)
Process descriptor:
eta_x
Xdot_dest
where:
eta_x = useful exergy output / accessible exergy input
Xdot_dest = T0 * Sdot_gen
A stream can have high fx and still be wasted in an irreversible device.
A stream can have low fx and still be valuable if it is well matched to a low-fx demand.
Machine-Readable Input Patterns
The library accepts incomplete records immediately, computes what it can, and returns:
- capabilities
- missing context
- assumptions
- warnings
- validation issues
This lets records improve over time instead of forcing every user through a fixed checklist.
The simplest machine-readable record only needs:
quantity or power
unit
fx or exergy_factor
For declared context, add:
reference
boundary
basis
For thermal streams, include source temperature and reference sink temperature when possible:
source_c
sink_c
For chemical carriers, declare the energy basis:
HHV
LHV
tabulated chemical exergy
Project Contents
src/quantity_quality/ Python package
data/reference_examples.json Canonical reference examples
data/reference_examples.csv Spreadsheet export
data/quantity_quality_record.schema.json
JSON Schema for interoperable records
examples/adoption_records.csv Cleaning example
examples/process_heat_comparison.json Scenario comparison example
docs/adoption-cookbook.md Practical adoption recipes
paper/ Framework paper
Development
python -m pip install -e ".[all,dev]"
python -m pytest -q
python -m build
The package is typed:
py.typed
and built as a pure Python wheel.
Citation
If you use this framework, examples, or code, please cite:
@misc{dimurro2026quantityquality,
title = {Quantity and Quality: A Standard Reporting Framework for Energy Systems},
author = {DiMurro, Christopher},
year = {2026},
note = {Independent Researcher, Exergy Lab}
}
After the arXiv version is available, replace this with the arXiv citation.
Machine-readable citation metadata is in CITATION.cff. GitHub
renders a formatted citation from it via the Cite this repository button in
the repository sidebar.
Contributing
Issues and pull requests are welcome, particularly:
- Reference examples for carriers or processes not yet covered, with a
stated boundary, basis, and source. New examples belong in
data/reference_examples.jsonand should come with a test. - Corrections to any published number. If a reference value here is wrong, that is the most valuable issue you can file — please include the working, not just the corrected value.
- Adoption reports: what broke when you pointed this at a real dataset.
Before opening a pull request:
python -m pip install -e ".[all,dev]"
python -m pytest -q
CI runs the test suite and a package build on Python 3.9 through 3.13.
Related
| exergyfactor.com | Browser calculator built on this package's reference data. No install required. |
| cdimurro/exergy-factor | Source for that site. |
License
MIT © 2026 Christopher DiMurro
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 quantity_and_quality-0.5.0.tar.gz.
File metadata
- Download URL: quantity_and_quality-0.5.0.tar.gz
- Upload date:
- Size: 56.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6806c3634e37b6e79e48af1e500177deb114d7181a68308f03ff354e88907e63
|
|
| MD5 |
751ccca61574b10960723263d38e2774
|
|
| BLAKE2b-256 |
7db9f8f3a1e91148d55ca4e146985fc493eaf74726a6195737423838a70bea2c
|
Provenance
The following attestation bundles were made for quantity_and_quality-0.5.0.tar.gz:
Publisher:
publish.yml on cdimurro/quantity-and-quality
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
quantity_and_quality-0.5.0.tar.gz -
Subject digest:
6806c3634e37b6e79e48af1e500177deb114d7181a68308f03ff354e88907e63 - Sigstore transparency entry: 2422851915
- Sigstore integration time:
-
Permalink:
cdimurro/quantity-and-quality@ce44dc2142dd3f23e31bd3879bde7beeda0f7665 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/cdimurro
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ce44dc2142dd3f23e31bd3879bde7beeda0f7665 -
Trigger Event:
release
-
Statement type:
File details
Details for the file quantity_and_quality-0.5.0-py3-none-any.whl.
File metadata
- Download URL: quantity_and_quality-0.5.0-py3-none-any.whl
- Upload date:
- Size: 60.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b8e97eb9f58674c08efa4dba72860723a3910b33f026a595bf850cc72490a989
|
|
| MD5 |
88f017a8ee73c40201b28c0cde032201
|
|
| BLAKE2b-256 |
3ee1aca0c8eb1669506d4a95bf788d0606e7a53be322d5c315f6392591db693e
|
Provenance
The following attestation bundles were made for quantity_and_quality-0.5.0-py3-none-any.whl:
Publisher:
publish.yml on cdimurro/quantity-and-quality
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
quantity_and_quality-0.5.0-py3-none-any.whl -
Subject digest:
b8e97eb9f58674c08efa4dba72860723a3910b33f026a595bf850cc72490a989 - Sigstore transparency entry: 2422851971
- Sigstore integration time:
-
Permalink:
cdimurro/quantity-and-quality@ce44dc2142dd3f23e31bd3879bde7beeda0f7665 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/cdimurro
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ce44dc2142dd3f23e31bd3879bde7beeda0f7665 -
Trigger Event:
release
-
Statement type: