loadcast 0.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
loadcast-0.1.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mattéo Hauglustaine
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,204 @@
1
+ Metadata-Version: 2.4
2
+ Name: loadcast
3
+ Version: 0.1.1
4
+ Summary: Synthetic multi-carrier industrial energy demand profiles with controllable cross-carrier structure
5
+ Author-email: Matteo Hauglustaine <matteo@abeo.be>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/Matt-haug/loadcast
8
+ Project-URL: Documentation, https://loadcast.readthedocs.io
9
+ Project-URL: Repository, https://github.com/Matt-haug/loadcast
10
+ Project-URL: Issues, https://github.com/Matt-haug/loadcast/issues
11
+ Keywords: energy,demand,load profile,industrial,synthetic data,time series,heat,cooling,multi-carrier
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Scientific/Engineering
20
+ Requires-Python: >=3.9
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Requires-Dist: numpy>=1.21
24
+ Requires-Dist: pandas>=1.3
25
+ Provides-Extra: plot
26
+ Requires-Dist: matplotlib>=3.5; extra == "plot"
27
+ Provides-Extra: test
28
+ Requires-Dist: pytest>=7.0; extra == "test"
29
+ Provides-Extra: docs
30
+ Requires-Dist: mkdocs>=1.5; extra == "docs"
31
+ Requires-Dist: mkdocs-material>=9.0; extra == "docs"
32
+ Requires-Dist: mkdocstrings[python]>=0.24; extra == "docs"
33
+ Provides-Extra: dev
34
+ Requires-Dist: loadcast[docs,plot,test]; extra == "dev"
35
+ Dynamic: license-file
36
+
37
+ [![PyPI version](https://img.shields.io/pypi/v/loadcast)](https://pypi.org/project/loadcast/)
38
+ [![Documentation Status](https://readthedocs.org/projects/loadcast/badge/?version=latest)](https://loadcast.readthedocs.io/en/latest/)
39
+ [![Build Status](https://github.com/Matt-haug/loadcast/actions/workflows/tests.yml/badge.svg)](https://github.com/Matt-haug/loadcast/actions/workflows/tests.yml)
40
+ [![License](https://img.shields.io/github/license/Matt-haug/loadcast)](https://github.com/Matt-haug/loadcast/blob/main/LICENSE)
41
+ [![DOI](https://img.shields.io/badge/DOI-10.5281%2Fzenodo.22961300-blue)](https://doi.org/10.5281/zenodo.22961300)
42
+
43
+ # loadcast
44
+
45
+ **A synthetic multi-carrier industrial energy demand generator**
46
+
47
+ ```python
48
+ import loadcast
49
+
50
+ profiles = loadcast.generate(
51
+ annual_mwh=10_000,
52
+ heat_to_cold=7.4, # this site wants 7.4x more heat than cold
53
+ elec_share=0.20, # a fifth of its energy is electricity
54
+ process_class="semi_continuous", # weekday shifts, weekend trough
55
+ carrier_correlation=0.75, # how tightly the carriers move together
56
+ carrier_lag_h={"cold": 6}, # cold demand trails heat by six hours
57
+ )
58
+ ```
59
+
60
+ Returns an 8760-row hourly or quarter-hourly frame of `heat_kw`, `cold_kw` and `elec_kw`.
61
+
62
+ ![Heat-cold cross-correlogram: the published disaggregated construction peaks at exactly 1.000; loadcast peaks at the 0.60 asked for](https://raw.githubusercontent.com/Matt-haug/loadcast/main/examples/figures/07_coincidence.png)
63
+
64
+ *Left: every carrier as a fixed multiple of one shared profile, the construction behind published
65
+ disaggregated data, which is correlated at 1 by algebra. Right: `loadcast` with `carrier_correlation=0.60`.
66
+ More in the [tutorial notebook](https://github.com/Matt-haug/loadcast/blob/main/examples/01_tutorial.ipynb).*
67
+
68
+ ## Why
69
+
70
+ Designing anything with storage against an industrial site needs to know not
71
+ just *how much* of each carrier the site wants, but **whether it wants them at
72
+ the same hours**. A store exists to bridge the gap when it does not.
73
+
74
+ Existing sources cannot answer that question:
75
+
76
+ | source | approach | industrial | coincidence controllable? |
77
+ |---|---|---|---|
78
+ | demandlib / BDEW SLP | deterministic step profiles | yes | no — deterministic |
79
+ | RAMP | bottom-up from appliances | no | no — emerges from user schedules |
80
+ | LoadProfileGenerator | behavioural simulation | no | no |
81
+ | EnTiSe | framework, pluggable methods | partly | no — pipeline dependency |
82
+ | JERICHO-E-usage | disaggregated national totals | yes | no — fixed at 1.000 |
83
+
84
+ The disaggregated datasets build every carrier as a fixed scalar times one
85
+ shared profile, $P_m(t) = \kappa_m p(t)$, under which the correlation between
86
+ any two carriers is identically 1 — an artefact of the construction, not a
87
+ measurement. Feeding that into a storage study builds the answer into the
88
+ question.
89
+
90
+ `loadcast` makes the relationship an input you set and sweep.
91
+
92
+ ## What you specify
93
+
94
+ Things you can answer from a site visit or an energy bill, not things the
95
+ mathematics wants:
96
+
97
+ | input | meaning |
98
+ |---|---|
99
+ | `annual_mwh` | total annual energy across all carriers |
100
+ | `heat_to_cold` | ratio of annual heat to annual cold |
101
+ | `elec_share` | electricity as a fraction of the total |
102
+ | `process_class` | continuous, semi-continuous, campaign or batch |
103
+ | `carrier_correlation` | how tightly carriers move together, at peak alignment |
104
+ | `carrier_lag_h` | hours by which a carrier trails the others |
105
+
106
+ The four process classes are calibrated on metered industrial sites. If none
107
+ fits yours, build one from your own statistics:
108
+
109
+ ```python
110
+ from loadcast import class_from_observations, register_class
111
+
112
+ mine = class_from_observations(
113
+ "my_plant", load_factor=0.45, cv=0.60, lag1=0.90,
114
+ calendar_from="semi_continuous",
115
+ )
116
+ register_class(mine)
117
+ profiles = loadcast.generate(process_class="my_plant", annual_mwh=5_000)
118
+ ```
119
+
120
+ The inversion from observables to generator parameters is closed form. See [mathematics](https://loadcast.readthedocs.io/en/latest/mathematics/) for details.
121
+
122
+ ## What it guarantees exactly
123
+
124
+ Not approximately, but to floating-point:
125
+
126
+ - annual energy equals `annual_mwh`
127
+ - the heat:cold ratio equals `heat_to_cold`
128
+ - the electricity share equals `elec_share`
129
+ - the load factor equals the process class's, via the capacity cap fixed point
130
+ - every value is strictly positive
131
+
132
+ ## Diagnostics
133
+
134
+ ```python
135
+ loadcast.summary_table(profiles) # the four scalars
136
+ loadcast.duration_curve(profiles["heat_kw"]) # load duration curve
137
+ loadcast.cross_correlogram(profiles["heat_kw"], profiles["cold_kw"])
138
+ loadcast.integrated_drift(profiles["heat_kw"], profiles["cold_kw"], window_h=24)
139
+ ```
140
+
141
+ Read the correlogram's **peak position**, not only its height. A lag and a weak
142
+ coupling are indistinguishable from the contemporaneous correlation alone: as
143
+ carriers are offset, the lag-0 correlation decays towards the floor the shared
144
+ calendar imposes, exactly where a small correlation would also put it.
145
+
146
+ `integrated_drift` is the quantity a store actually responds to. A buffer does
147
+ not sample a mismatch, it integrates one, so what sizes it is the area under the
148
+ mismatch autocovariance over the storage window — correlation is a single point
149
+ of that picture.
150
+
151
+ ## What it deliberately does not do
152
+
153
+ - **No temperature.** It carries energy by carrier. Whether a machine can
154
+ *reach* a given process is a separate question, answered from the machine's
155
+ own limits.
156
+ - **No claim about your site.** Parameters are yours to choose; defaults are
157
+ indicative values with a stated provenance, not predictions. Results are meant
158
+ to be reported as they hold across a swept space, not at one assumed point.
159
+ - **No cold validation.** No site in the calibration archive meters
160
+ refrigeration. The cold carrier's annual quantity is whatever you specify;
161
+ its *shape* rests on the same calendar and correlation assumptions as the
162
+ others, and nothing independent confirms it. Every cold result carries this.
163
+
164
+ ## Install
165
+
166
+ ```bash
167
+ pip install loadcast
168
+ ```
169
+
170
+ Requires Python 3.9+, numpy and pandas. Nothing else.
171
+
172
+ ## Documentation
173
+
174
+ A detailed documentation of the library is available at: https://loadcast.readthedocs.io/en/latest/
175
+
176
+ Refer to that documentation for usage instructions and examples and details of the method.
177
+
178
+ ## Calibration data
179
+
180
+ The process classes are calibrated on metered industrial sites that cannot be
181
+ redistributed. What ships is the *derived* statistics and calendar factors —
182
+ group means carrying no identifying information. The raw series are not part of
183
+ this repository.
184
+
185
+ ## Contributing
186
+
187
+ Issues and pull requests are welcome — see [CONTRIBUTING.md](https://github.com/Matt-haug/loadcast/blob/main/CONTRIBUTING.md)
188
+ for scope, what a test looks like here, and support expectations. Reports that
189
+ the generated profiles disagree with a real site you have measured are
190
+ especially welcome: the calibration archive is small, and that is the package's
191
+ main limitation.
192
+
193
+ This project follows the [Contributor Covenant](https://github.com/Matt-haug/loadcast/blob/main/CODE_OF_CONDUCT.md).
194
+ Generative AI was used in building it; see [AI_USAGE.md](https://github.com/Matt-haug/loadcast/blob/main/AI_USAGE.md).
195
+
196
+ ## Citing
197
+
198
+ Use the "Cite this repository" button, or `CITATION.cff`. Each release is
199
+ archived on Zenodo with a DOI.
200
+
201
+ ## Licence
202
+
203
+ MIT — see [LICENSE](https://github.com/Matt-haug/loadcast/blob/main/LICENSE). Changes are recorded in
204
+ [CHANGELOG.md](https://github.com/Matt-haug/loadcast/blob/main/CHANGELOG.md).
@@ -0,0 +1,168 @@
1
+ [![PyPI version](https://img.shields.io/pypi/v/loadcast)](https://pypi.org/project/loadcast/)
2
+ [![Documentation Status](https://readthedocs.org/projects/loadcast/badge/?version=latest)](https://loadcast.readthedocs.io/en/latest/)
3
+ [![Build Status](https://github.com/Matt-haug/loadcast/actions/workflows/tests.yml/badge.svg)](https://github.com/Matt-haug/loadcast/actions/workflows/tests.yml)
4
+ [![License](https://img.shields.io/github/license/Matt-haug/loadcast)](https://github.com/Matt-haug/loadcast/blob/main/LICENSE)
5
+ [![DOI](https://img.shields.io/badge/DOI-10.5281%2Fzenodo.22961300-blue)](https://doi.org/10.5281/zenodo.22961300)
6
+
7
+ # loadcast
8
+
9
+ **A synthetic multi-carrier industrial energy demand generator**
10
+
11
+ ```python
12
+ import loadcast
13
+
14
+ profiles = loadcast.generate(
15
+ annual_mwh=10_000,
16
+ heat_to_cold=7.4, # this site wants 7.4x more heat than cold
17
+ elec_share=0.20, # a fifth of its energy is electricity
18
+ process_class="semi_continuous", # weekday shifts, weekend trough
19
+ carrier_correlation=0.75, # how tightly the carriers move together
20
+ carrier_lag_h={"cold": 6}, # cold demand trails heat by six hours
21
+ )
22
+ ```
23
+
24
+ Returns an 8760-row hourly or quarter-hourly frame of `heat_kw`, `cold_kw` and `elec_kw`.
25
+
26
+ ![Heat-cold cross-correlogram: the published disaggregated construction peaks at exactly 1.000; loadcast peaks at the 0.60 asked for](https://raw.githubusercontent.com/Matt-haug/loadcast/main/examples/figures/07_coincidence.png)
27
+
28
+ *Left: every carrier as a fixed multiple of one shared profile, the construction behind published
29
+ disaggregated data, which is correlated at 1 by algebra. Right: `loadcast` with `carrier_correlation=0.60`.
30
+ More in the [tutorial notebook](https://github.com/Matt-haug/loadcast/blob/main/examples/01_tutorial.ipynb).*
31
+
32
+ ## Why
33
+
34
+ Designing anything with storage against an industrial site needs to know not
35
+ just *how much* of each carrier the site wants, but **whether it wants them at
36
+ the same hours**. A store exists to bridge the gap when it does not.
37
+
38
+ Existing sources cannot answer that question:
39
+
40
+ | source | approach | industrial | coincidence controllable? |
41
+ |---|---|---|---|
42
+ | demandlib / BDEW SLP | deterministic step profiles | yes | no — deterministic |
43
+ | RAMP | bottom-up from appliances | no | no — emerges from user schedules |
44
+ | LoadProfileGenerator | behavioural simulation | no | no |
45
+ | EnTiSe | framework, pluggable methods | partly | no — pipeline dependency |
46
+ | JERICHO-E-usage | disaggregated national totals | yes | no — fixed at 1.000 |
47
+
48
+ The disaggregated datasets build every carrier as a fixed scalar times one
49
+ shared profile, $P_m(t) = \kappa_m p(t)$, under which the correlation between
50
+ any two carriers is identically 1 — an artefact of the construction, not a
51
+ measurement. Feeding that into a storage study builds the answer into the
52
+ question.
53
+
54
+ `loadcast` makes the relationship an input you set and sweep.
55
+
56
+ ## What you specify
57
+
58
+ Things you can answer from a site visit or an energy bill, not things the
59
+ mathematics wants:
60
+
61
+ | input | meaning |
62
+ |---|---|
63
+ | `annual_mwh` | total annual energy across all carriers |
64
+ | `heat_to_cold` | ratio of annual heat to annual cold |
65
+ | `elec_share` | electricity as a fraction of the total |
66
+ | `process_class` | continuous, semi-continuous, campaign or batch |
67
+ | `carrier_correlation` | how tightly carriers move together, at peak alignment |
68
+ | `carrier_lag_h` | hours by which a carrier trails the others |
69
+
70
+ The four process classes are calibrated on metered industrial sites. If none
71
+ fits yours, build one from your own statistics:
72
+
73
+ ```python
74
+ from loadcast import class_from_observations, register_class
75
+
76
+ mine = class_from_observations(
77
+ "my_plant", load_factor=0.45, cv=0.60, lag1=0.90,
78
+ calendar_from="semi_continuous",
79
+ )
80
+ register_class(mine)
81
+ profiles = loadcast.generate(process_class="my_plant", annual_mwh=5_000)
82
+ ```
83
+
84
+ The inversion from observables to generator parameters is closed form. See [mathematics](https://loadcast.readthedocs.io/en/latest/mathematics/) for details.
85
+
86
+ ## What it guarantees exactly
87
+
88
+ Not approximately, but to floating-point:
89
+
90
+ - annual energy equals `annual_mwh`
91
+ - the heat:cold ratio equals `heat_to_cold`
92
+ - the electricity share equals `elec_share`
93
+ - the load factor equals the process class's, via the capacity cap fixed point
94
+ - every value is strictly positive
95
+
96
+ ## Diagnostics
97
+
98
+ ```python
99
+ loadcast.summary_table(profiles) # the four scalars
100
+ loadcast.duration_curve(profiles["heat_kw"]) # load duration curve
101
+ loadcast.cross_correlogram(profiles["heat_kw"], profiles["cold_kw"])
102
+ loadcast.integrated_drift(profiles["heat_kw"], profiles["cold_kw"], window_h=24)
103
+ ```
104
+
105
+ Read the correlogram's **peak position**, not only its height. A lag and a weak
106
+ coupling are indistinguishable from the contemporaneous correlation alone: as
107
+ carriers are offset, the lag-0 correlation decays towards the floor the shared
108
+ calendar imposes, exactly where a small correlation would also put it.
109
+
110
+ `integrated_drift` is the quantity a store actually responds to. A buffer does
111
+ not sample a mismatch, it integrates one, so what sizes it is the area under the
112
+ mismatch autocovariance over the storage window — correlation is a single point
113
+ of that picture.
114
+
115
+ ## What it deliberately does not do
116
+
117
+ - **No temperature.** It carries energy by carrier. Whether a machine can
118
+ *reach* a given process is a separate question, answered from the machine's
119
+ own limits.
120
+ - **No claim about your site.** Parameters are yours to choose; defaults are
121
+ indicative values with a stated provenance, not predictions. Results are meant
122
+ to be reported as they hold across a swept space, not at one assumed point.
123
+ - **No cold validation.** No site in the calibration archive meters
124
+ refrigeration. The cold carrier's annual quantity is whatever you specify;
125
+ its *shape* rests on the same calendar and correlation assumptions as the
126
+ others, and nothing independent confirms it. Every cold result carries this.
127
+
128
+ ## Install
129
+
130
+ ```bash
131
+ pip install loadcast
132
+ ```
133
+
134
+ Requires Python 3.9+, numpy and pandas. Nothing else.
135
+
136
+ ## Documentation
137
+
138
+ A detailed documentation of the library is available at: https://loadcast.readthedocs.io/en/latest/
139
+
140
+ Refer to that documentation for usage instructions and examples and details of the method.
141
+
142
+ ## Calibration data
143
+
144
+ The process classes are calibrated on metered industrial sites that cannot be
145
+ redistributed. What ships is the *derived* statistics and calendar factors —
146
+ group means carrying no identifying information. The raw series are not part of
147
+ this repository.
148
+
149
+ ## Contributing
150
+
151
+ Issues and pull requests are welcome — see [CONTRIBUTING.md](https://github.com/Matt-haug/loadcast/blob/main/CONTRIBUTING.md)
152
+ for scope, what a test looks like here, and support expectations. Reports that
153
+ the generated profiles disagree with a real site you have measured are
154
+ especially welcome: the calibration archive is small, and that is the package's
155
+ main limitation.
156
+
157
+ This project follows the [Contributor Covenant](https://github.com/Matt-haug/loadcast/blob/main/CODE_OF_CONDUCT.md).
158
+ Generative AI was used in building it; see [AI_USAGE.md](https://github.com/Matt-haug/loadcast/blob/main/AI_USAGE.md).
159
+
160
+ ## Citing
161
+
162
+ Use the "Cite this repository" button, or `CITATION.cff`. Each release is
163
+ archived on Zenodo with a DOI.
164
+
165
+ ## Licence
166
+
167
+ MIT — see [LICENSE](https://github.com/Matt-haug/loadcast/blob/main/LICENSE). Changes are recorded in
168
+ [CHANGELOG.md](https://github.com/Matt-haug/loadcast/blob/main/CHANGELOG.md).
@@ -0,0 +1,61 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "loadcast"
7
+ version = "0.1.1"
8
+ description = "Synthetic multi-carrier industrial energy demand profiles with controllable cross-carrier structure"
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = "MIT"
12
+ authors = [
13
+ { name = "Matteo Hauglustaine", email = "matteo@abeo.be" },
14
+ ]
15
+ keywords = [
16
+ "energy",
17
+ "demand",
18
+ "load profile",
19
+ "industrial",
20
+ "synthetic data",
21
+ "time series",
22
+ "heat",
23
+ "cooling",
24
+ "multi-carrier",
25
+ ]
26
+ classifiers = [
27
+ "Development Status :: 4 - Beta",
28
+ "Intended Audience :: Science/Research",
29
+ "Programming Language :: Python :: 3",
30
+ "Programming Language :: Python :: 3.9",
31
+ "Programming Language :: Python :: 3.10",
32
+ "Programming Language :: Python :: 3.11",
33
+ "Programming Language :: Python :: 3.12",
34
+ "Topic :: Scientific/Engineering",
35
+ ]
36
+ dependencies = [
37
+ "numpy>=1.21",
38
+ "pandas>=1.3",
39
+ ]
40
+
41
+ [project.optional-dependencies]
42
+ plot = ["matplotlib>=3.5"]
43
+ test = ["pytest>=7.0"]
44
+ docs = ["mkdocs>=1.5", "mkdocs-material>=9.0", "mkdocstrings[python]>=0.24"]
45
+ dev = ["loadcast[plot,test,docs]"]
46
+
47
+ [project.urls]
48
+ Homepage = "https://github.com/Matt-haug/loadcast"
49
+ Documentation = "https://loadcast.readthedocs.io"
50
+ Repository = "https://github.com/Matt-haug/loadcast"
51
+ Issues = "https://github.com/Matt-haug/loadcast/issues"
52
+
53
+ [tool.setuptools.packages.find]
54
+ where = ["src"]
55
+
56
+ [tool.setuptools.package-data]
57
+ loadcast = ["data/*.json"]
58
+
59
+ [tool.pytest.ini_options]
60
+ testpaths = ["tests"]
61
+ addopts = "-q"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,94 @@
1
+ """loadcast -- synthetic multi-carrier industrial energy demand.
2
+
3
+ Hourly heat, cold and electricity demand for an industrial site, from the
4
+ handful of numbers someone actually knows about a plant: how much energy it uses
5
+ in a year, roughly how much more heat than cold it wants, how much of the
6
+ total is electricity, and whether the process runs continuously, in shifts or in
7
+ batches.
8
+
9
+ import loadcast
10
+
11
+ profiles = loadcast.generate(
12
+ annual_mwh=10_000,
13
+ heat_to_cold=7.4,
14
+ elec_share=0.20,
15
+ process_class="semi_continuous",
16
+ )
17
+
18
+ What makes it different
19
+ -----------------------
20
+ Existing tools either produce deterministic profiles or leave the relationship
21
+ between carriers to fall out of whatever drives them. Both give carriers that
22
+ move in lockstep, which is an artefact of the construction rather than a
23
+ property of industry -- and for anything with storage, *whether the carriers
24
+ peak together* is precisely what decides how much buffering is needed.
25
+
26
+ loadcast makes that relationship an explicit input. `carrier_correlation` sets
27
+ how tightly the carriers move together and `carrier_lag_h` sets how far apart
28
+ they are offset, so a study can sweep coincidence rather than inherit it.
29
+
30
+ What it does not do
31
+ -------------------
32
+ It carries energy by carrier, not temperature: whether a machine can *reach* a
33
+ given process is a separate question, answered from the machine's own limits.
34
+ And the parameters are yours to choose. Defaults are indicative values with a
35
+ stated provenance, not predictions about any real site -- results are meant to
36
+ be reported as they hold across a swept space, not at a single assumed point.
37
+ """
38
+
39
+ from __future__ import annotations
40
+
41
+ from .classes import (
42
+ ProcessClass,
43
+ available_classes,
44
+ get_class,
45
+ load_classes,
46
+ register_class,
47
+ )
48
+ from .fitting import (
49
+ bias_report,
50
+ class_from_observations,
51
+ correlation_floor,
52
+ correlation_transfer,
53
+ phi_from_lag1,
54
+ sigma_from_cv,
55
+ )
56
+ from . import reference
57
+ from .generator import (
58
+ build_profiles,
59
+ generate,
60
+ rescale_persistence,
61
+ solve_correlation_knob,
62
+ step_hours,
63
+ )
64
+ from .spec import CARRIERS, DemandSpec
65
+ from .stats import (
66
+ cross_correlogram,
67
+ duration_curve,
68
+ integrated_drift,
69
+ profile_statistics,
70
+ summary_table,
71
+ )
72
+
73
+ __version__ = "0.1.1"
74
+
75
+ __all__ = [
76
+ "__version__",
77
+ # what to generate
78
+ "DemandSpec", "CARRIERS",
79
+ # generating
80
+ "generate", "build_profiles", "solve_correlation_knob",
81
+ "step_hours", "rescale_persistence",
82
+ # process classes
83
+ "ProcessClass", "available_classes", "get_class", "load_classes",
84
+ "register_class",
85
+ # fitting to your own measurements
86
+ "class_from_observations", "bias_report",
87
+ "sigma_from_cv", "phi_from_lag1",
88
+ "correlation_floor", "correlation_transfer",
89
+ # diagnostics
90
+ # indicative published values
91
+ "reference",
92
+ "profile_statistics", "summary_table", "duration_curve",
93
+ "cross_correlogram", "integrated_drift",
94
+ ]