You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add optional reference (production) exchange column to datapackage schema (#108)
Adds an optional per-exchange `reference` boolean column, stored as its own
side-resource (`kind="reference"`) exactly like `flip`/`rescale`: additive,
backward compatible, and written only when at least one entry is flagged.
Modellers can now record which technosphere exchange is the reference
(production) exchange, so consumers such as bw_graph_tools can read it
directly instead of relying on structural heuristics, which cannot
disambiguate co-production columns (an activity with multiple same-sign
outputs whose products also appear in other columns).
- MatrixEntry.reference / ArrayEntry.reference
- reference_array kwarg on all add_* methods + _add_reference_array_resource
- threaded through dictionary_formatter / resolve_dict_iterator
- "reference" added to Parquet kind mapping and merging suffix whitelist
- README section, CHANGES entry, version bump 1.5 -> 1.6
- tests: dataclass defaults/validation, low-level validation, skip-when-empty,
write->reload round-trip
Refs cauldron/brightway-api#739
Copy file name to clipboardExpand all lines: CHANGES.md
+4Lines changed: 4 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,5 +1,9 @@
1
1
# `bw_processing` Changelog
2
2
3
+
## [1.6] - 2026-07-10
4
+
5
+
* Add optional `reference` boolean column marking reference (production) exchanges. Stored as a `reference_array` side-resource (`kind="reference"`) analogous to `flip`, and exposed on `MatrixEntry`/`ArrayEntry` and all `add_*` methods. Lets modellers record the reference exchange explicitly instead of relying on `bw_graph_tools`' structural heuristics, which cannot disambiguate co-production columns. See cauldron/brightway-api#739.
6
+
3
7
## [1.5] - 2026-06-04
4
8
5
9
*[PR #100: Deduplicate chunked bucket-fill logic; fix #95 and #97](https://github.com/brightway-lca/bw_processing/pull/100)
Copy file name to clipboardExpand all lines: README.md
+33-6Lines changed: 33 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -168,12 +168,12 @@ print(data_obj.url)
168
168
169
169
### Scale arrays
170
170
171
-
Any resource group (persistent or dynamic, vector or array) can carry an optional `scale_array`: a one-dimensional float array of the same length as `indices_array`. Each element is a multiplicative factor applied to the corresponding data value before it is inserted into the matrix. The factor is applied to both static and stochastically-sampled values. A value of `1.0` leaves the data unchanged.
171
+
Any resource group (persistent or dynamic, vector or array) can carry an optional `rescale_array`: a one-dimensional float array of the same length as `indices_array`. Each element is a multiplicative factor applied to the corresponding data value before it is inserted into the matrix. The factor is applied to both static and stochastically-sampled values. A value of `1.0` leaves the data unchanged.
172
172
173
173
Typical use cases:
174
174
175
-
***Allocation factors** — when a process produces multiple products, the exchange amounts must be partitioned between them. Storing the allocation coefficients as a `scale_array` keeps them alongside the data they modify without requiring a separate processing step.
176
-
***Unit conversions** — when source data is expressed in a unit that differs from the matrix convention, a constant conversion factor can be stored as a `scale_array` rather than baked into every data value.
175
+
***Allocation factors** — when a process produces multiple products, the exchange amounts must be partitioned between them. Storing the allocation coefficients as a `rescale_array` keeps them alongside the data they modify without requiring a separate processing step.
176
+
***Unit conversions** — when source data is expressed in a unit that differs from the matrix convention, a constant conversion factor can be stored as a `rescale_array` rather than baked into every data value.
177
177
178
178
```python
179
179
import numpy as np
@@ -183,18 +183,45 @@ from bw_processing.constants import INDICES_DTYPE
scale_array= np.array([0.6, 1.0, 0.4]) # e.g. allocation factors
186
+
rescale_array= np.array([0.6, 1.0, 0.4]) # e.g. allocation factors
187
187
188
188
dp.add_persistent_vector(
189
189
matrix="technosphere",
190
190
name="my-process",
191
191
indices_array=indices_array,
192
192
data_array=data_array,
193
-
scale_array=scale_array,
193
+
rescale_array=rescale_array,
194
194
)
195
195
```
196
196
197
-
The stored resource has `kind="scale"` and can be retrieved via `dp.get_resource("my-process.scale")`. The `scale_array` must be a float dtype (`float32` or `float64`); passing an integer array raises `WrongDatatype`.
197
+
The stored resource has `kind="rescale"` and can be retrieved via `dp.get_resource("my-process.rescale")`. The `rescale_array` must be a float dtype (`float32` or `float64`); passing an integer array raises `WrongDatatype`.
198
+
199
+
### Reference (production) exchanges
200
+
201
+
Any resource group can also carry an optional `reference_array`: a one-dimensional boolean array of the same length as `indices_array`. Where an element is `True`, that exchange is the **reference (production) exchange** for its activity/column.
202
+
203
+
The five structural heuristics in `bw_graph_tools` (matching ids, single non-flipped entry, single positive, single negative, unique product) cannot always identify the reference exchange — whenever an activity has more than one same-sign exchange and the products also appear in other columns, the choice is genuinely ambiguous. Only the modeller knows the answer. `reference_array` records it directly so downstream tools can read it instead of guessing.
reference_array = np.array([True, False, False]) # first exchange is the reference
214
+
215
+
dp.add_persistent_vector(
216
+
matrix="technosphere",
217
+
name="my-process",
218
+
indices_array=indices_array,
219
+
data_array=data_array,
220
+
reference_array=reference_array,
221
+
)
222
+
```
223
+
224
+
The stored resource has `kind="reference"` and can be retrieved via `dp.get_resource("my-process.reference")`. It must be a boolean array; passing a non-boolean array raises `WrongDatatype`. To keep the common case cheap, the resource is written only when at least one entry is `True` — a group with no reference flags carries no `reference` resource. Using the high-level `MatrixEntry`/`ArrayEntry` API, set `reference=True` (or a boolean `reference` array) on the entries you want flagged.
0 commit comments