bw-processing 1.0__tar.gz → 1.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.
- bw_processing-1.1.1/MANIFEST.in +3 -0
- {bw_processing-1.0/bw_processing.egg-info → bw_processing-1.1.1}/PKG-INFO +4 -3
- {bw_processing-1.0 → bw_processing-1.1.1}/README.md +1 -1
- {bw_processing-1.0 → bw_processing-1.1.1}/pyproject.toml +3 -1
- bw_processing-1.1.1/src/bw_processing/__init__.py +52 -0
- {bw_processing-1.0 → bw_processing-1.1.1/src}/bw_processing/datapackage.py +44 -7
- {bw_processing-1.0 → bw_processing-1.1.1/src}/bw_processing/indexing.py +2 -2
- {bw_processing-1.0 → bw_processing-1.1.1/src}/bw_processing/io_helpers.py +4 -4
- {bw_processing-1.0 → bw_processing-1.1.1/src}/bw_processing/io_parquet_helpers.py +2 -2
- bw_processing-1.1.1/src/bw_processing/matrix_entry.py +128 -0
- {bw_processing-1.0 → bw_processing-1.1.1/src}/bw_processing/merging.py +3 -3
- {bw_processing-1.0 → bw_processing-1.1.1/src}/bw_processing/unique_fields.py +1 -1
- {bw_processing-1.0 → bw_processing-1.1.1/src}/bw_processing/utils.py +3 -3
- {bw_processing-1.0 → bw_processing-1.1.1/src/bw_processing.egg-info}/PKG-INFO +4 -3
- bw_processing-1.1.1/src/bw_processing.egg-info/SOURCES.txt +52 -0
- {bw_processing-1.0 → bw_processing-1.1.1}/tests/test_io_parquet_helpers.py +36 -53
- bw_processing-1.1.1/tests/test_matrix_entry.py +178 -0
- bw_processing-1.0/MANIFEST.in +0 -3
- bw_processing-1.0/bw_processing/__init__.py +0 -48
- bw_processing-1.0/bw_processing.egg-info/SOURCES.txt +0 -50
- {bw_processing-1.0 → bw_processing-1.1.1}/LICENSE +0 -0
- {bw_processing-1.0 → bw_processing-1.1.1}/setup.cfg +0 -0
- {bw_processing-1.0 → bw_processing-1.1.1/src}/bw_processing/array_creation.py +0 -0
- {bw_processing-1.0 → bw_processing-1.1.1/src}/bw_processing/constants.py +0 -0
- {bw_processing-1.0 → bw_processing-1.1.1/src}/bw_processing/errors.py +0 -0
- {bw_processing-1.0 → bw_processing-1.1.1/src}/bw_processing/examples/__init__.py +0 -0
- {bw_processing-1.0 → bw_processing-1.1.1/src}/bw_processing/examples/datapackage_1/another name.indices.parquet +0 -0
- {bw_processing-1.0 → bw_processing-1.1.1/src}/bw_processing/examples/datapackage_1/sa-data-vector-from-dict.data.parquet +0 -0
- {bw_processing-1.0 → bw_processing-1.1.1/src}/bw_processing/examples/datapackage_1/sa-data-vector-from-dict.distributions.parquet +0 -0
- {bw_processing-1.0 → bw_processing-1.1.1/src}/bw_processing/examples/datapackage_1/sa-data-vector-from-dict.flip.parquet +0 -0
- {bw_processing-1.0 → bw_processing-1.1.1/src}/bw_processing/examples/datapackage_1/sa-data-vector-from-dict.indices.parquet +0 -0
- {bw_processing-1.0 → bw_processing-1.1.1/src}/bw_processing/examples/datapackage_1/some name.data.parquet +0 -0
- {bw_processing-1.0 → bw_processing-1.1.1/src}/bw_processing/examples/datapackage_1/some name.flip.parquet +0 -0
- {bw_processing-1.0 → bw_processing-1.1.1/src}/bw_processing/examples/datapackage_1/some name.indices.parquet +0 -0
- {bw_processing-1.0 → bw_processing-1.1.1/src}/bw_processing/examples/datapackage_2.zip +0 -0
- {bw_processing-1.0 → bw_processing-1.1.1/src}/bw_processing/examples/interfaces.py +0 -0
- {bw_processing-1.0 → bw_processing-1.1.1/src}/bw_processing/examples/parquet_files.py +0 -0
- {bw_processing-1.0 → bw_processing-1.1.1/src}/bw_processing/examples/simple.zip +0 -0
- {bw_processing-1.0 → bw_processing-1.1.1/src}/bw_processing/filesystem.py +0 -0
- {bw_processing-1.0 → bw_processing-1.1.1/src}/bw_processing/io_pyarrow_helpers.py +0 -0
- {bw_processing-1.0 → bw_processing-1.1.1/src}/bw_processing/proxies.py +0 -0
- {bw_processing-1.0 → bw_processing-1.1.1/src}/bw_processing.egg-info/dependency_links.txt +0 -0
- {bw_processing-1.0 → bw_processing-1.1.1/src}/bw_processing.egg-info/requires.txt +0 -0
- {bw_processing-1.0 → bw_processing-1.1.1/src}/bw_processing.egg-info/top_level.txt +0 -0
- {bw_processing-1.0 → bw_processing-1.1.1}/tests/test_array_creation.py +0 -0
- {bw_processing-1.0 → bw_processing-1.1.1}/tests/test_datapackage.py +0 -0
- {bw_processing-1.0 → bw_processing-1.1.1}/tests/test_filesystem.py +0 -0
- {bw_processing-1.0 → bw_processing-1.1.1}/tests/test_filtered_datapackage.py +0 -0
- {bw_processing-1.0 → bw_processing-1.1.1}/tests/test_indexing.py +0 -0
- {bw_processing-1.0 → bw_processing-1.1.1}/tests/test_integration.py +0 -0
- {bw_processing-1.0 → bw_processing-1.1.1}/tests/test_interfaces.py +0 -0
- {bw_processing-1.0 → bw_processing-1.1.1}/tests/test_io_pyarrow_helpers.py +0 -0
- {bw_processing-1.0 → bw_processing-1.1.1}/tests/test_loading.py +0 -0
- {bw_processing-1.0 → bw_processing-1.1.1}/tests/test_merging.py +0 -0
- {bw_processing-1.0 → bw_processing-1.1.1}/tests/test_proxies.py +0 -0
- {bw_processing-1.0 → bw_processing-1.1.1}/tests/test_unique_fields.py +0 -0
- {bw_processing-1.0 → bw_processing-1.1.1}/tests/test_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: bw_processing
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.1.1
|
|
4
4
|
Summary: Foo
|
|
5
5
|
Author-email: Chris Mutel <cmutel@gmail.com>
|
|
6
6
|
Maintainer-email: Chris Mutel <cmutel@gmail.com>
|
|
@@ -38,6 +38,7 @@ Requires-Dist: pytest; extra == "dev"
|
|
|
38
38
|
Requires-Dist: pytest-cov; extra == "dev"
|
|
39
39
|
Requires-Dist: pytest-randomly; extra == "dev"
|
|
40
40
|
Requires-Dist: setuptools; extra == "dev"
|
|
41
|
+
Dynamic: license-file
|
|
41
42
|
|
|
42
43
|
# bw-processing
|
|
43
44
|
|
|
@@ -81,7 +82,7 @@ The [Brightway LCA framework](https://brightway.dev/) has stored data used in co
|
|
|
81
82
|
* **Support for vector and array data**. Vector (i.e. only one possible value per input) and array (i.e. many possible values, also called presamples) data are now both natively supported in data packages.
|
|
82
83
|
* **Portability**. Processed arrays can include metadata that allows for reindexing on other machines, so that processed arrays can be distributed and reused. Before, this was not possible, as integer IDs were randomly assigned on each computer, and would be different from machine to machine or even across Brightway projects.
|
|
83
84
|
* **Dynamic data sources**. Instead of requiring that data for matrix construction be present and savedd on disk, it can now be generated dynamically, either through code running locally or on another computer system. This is a big step towards embeddding life cycle assessment in a web of environmental models.
|
|
84
|
-
* **Use [
|
|
85
|
+
* **Use [fsspec](https://filesystem-spec.readthedocs.io/en/latest/) for file IO**. The use of this library allows for data packages to be stored on your local computer, or on [many logical or virtual file systems](https://docs.pyfilesystem.org/en/latest/guide.html).
|
|
85
86
|
* **Simpler handling of numeric values whose sign should be flipped**. Sometimes it is more convenient to specify positive numbers in dataset definitions, even though such numbers should be negative when inserted into the resulting matrices. For example, in the technosphere matrix in life cycle assessment, products produced are positive and products consumed are negative, though both values are given as positive in datasets. Brightway used to use a type mapping dictionary to indicate which values in a matrix should have their sign flipped after insertion. Such mapping dictionaries are brittle and inelegant. `bw_processing` uses an optional boolean vector, called `flip`, to indicate if any values should be flipped.
|
|
86
87
|
* **Separation of uncertainty distribution parameters from other data**. Fitting data to a [probability density function](https://en.wikipedia.org/wiki/Probability_density_function) (PDF), or an estimate of such a PDF, is only one approach to quantitative uncertainty analysis. We would like to support other approaches, including [direct sampling from real data](https://github.com/PascalLesage/presamples/). Therefore, uncertainty distribution parameters are stored separately, only loaded if needed, and are only one way to express quantitative uncertainty.
|
|
87
88
|
|
|
@@ -40,7 +40,7 @@ The [Brightway LCA framework](https://brightway.dev/) has stored data used in co
|
|
|
40
40
|
* **Support for vector and array data**. Vector (i.e. only one possible value per input) and array (i.e. many possible values, also called presamples) data are now both natively supported in data packages.
|
|
41
41
|
* **Portability**. Processed arrays can include metadata that allows for reindexing on other machines, so that processed arrays can be distributed and reused. Before, this was not possible, as integer IDs were randomly assigned on each computer, and would be different from machine to machine or even across Brightway projects.
|
|
42
42
|
* **Dynamic data sources**. Instead of requiring that data for matrix construction be present and savedd on disk, it can now be generated dynamically, either through code running locally or on another computer system. This is a big step towards embeddding life cycle assessment in a web of environmental models.
|
|
43
|
-
* **Use [
|
|
43
|
+
* **Use [fsspec](https://filesystem-spec.readthedocs.io/en/latest/) for file IO**. The use of this library allows for data packages to be stored on your local computer, or on [many logical or virtual file systems](https://docs.pyfilesystem.org/en/latest/guide.html).
|
|
44
44
|
* **Simpler handling of numeric values whose sign should be flipped**. Sometimes it is more convenient to specify positive numbers in dataset definitions, even though such numbers should be negative when inserted into the resulting matrices. For example, in the technosphere matrix in life cycle assessment, products produced are positive and products consumed are negative, though both values are given as positive in datasets. Brightway used to use a type mapping dictionary to indicate which values in a matrix should have their sign flipped after insertion. Such mapping dictionaries are brittle and inelegant. `bw_processing` uses an optional boolean vector, called `flip`, to indicate if any values should be flipped.
|
|
45
45
|
* **Separation of uncertainty distribution parameters from other data**. Fitting data to a [probability density function](https://en.wikipedia.org/wiki/Probability_density_function) (PDF), or an estimate of such a PDF, is only one approach to quantitative uncertainty analysis. We would like to support other approaches, including [direct sampling from real data](https://github.com/PascalLesage/presamples/). Therefore, uncertainty distribution parameters are stored separately, only loaded if needed, and are only one way to express quantitative uncertainty.
|
|
46
46
|
|
|
@@ -66,7 +66,9 @@ dev = [
|
|
|
66
66
|
[tool.setuptools]
|
|
67
67
|
license-files = ["LICENSE"]
|
|
68
68
|
include-package-data = true
|
|
69
|
-
|
|
69
|
+
|
|
70
|
+
[tool.setuptools.packages.find]
|
|
71
|
+
where = ["src"]
|
|
70
72
|
|
|
71
73
|
[tool.setuptools.dynamic]
|
|
72
74
|
version = {attr = "bw_processing.__version__"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
__all__ = (
|
|
2
|
+
"__version__",
|
|
3
|
+
"as_unique_attributes",
|
|
4
|
+
"as_unique_attributes_dataframe",
|
|
5
|
+
"clean_datapackage_name",
|
|
6
|
+
"create_array",
|
|
7
|
+
"create_datapackage",
|
|
8
|
+
"create_datapackage_from_entries",
|
|
9
|
+
"create_structured_array",
|
|
10
|
+
"Datapackage",
|
|
11
|
+
"DatapackageBase",
|
|
12
|
+
"DEFAULT_LICENSES",
|
|
13
|
+
"examples_dir",
|
|
14
|
+
"FilteredDatapackage",
|
|
15
|
+
"generic_directory_filesystem",
|
|
16
|
+
"generic_zipfile_filesystem",
|
|
17
|
+
"INDICES_DTYPE",
|
|
18
|
+
"load_datapackage",
|
|
19
|
+
"MatrixEntry",
|
|
20
|
+
"MatrixName",
|
|
21
|
+
"MatrixSerializeFormat",
|
|
22
|
+
"md5",
|
|
23
|
+
"merge_datapackages_with_mask",
|
|
24
|
+
"reindex",
|
|
25
|
+
"reset_index",
|
|
26
|
+
"safe_filename",
|
|
27
|
+
"simple_graph",
|
|
28
|
+
"UNCERTAINTY_DTYPE",
|
|
29
|
+
"UndefinedInterface",
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
__version__ = "1.1.1"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
from bw_processing.array_creation import create_array, create_structured_array
|
|
36
|
+
from bw_processing.constants import DEFAULT_LICENSES, INDICES_DTYPE, UNCERTAINTY_DTYPE, MatrixSerializeFormat
|
|
37
|
+
from bw_processing.datapackage import (
|
|
38
|
+
Datapackage,
|
|
39
|
+
DatapackageBase,
|
|
40
|
+
FilteredDatapackage,
|
|
41
|
+
create_datapackage,
|
|
42
|
+
load_datapackage,
|
|
43
|
+
simple_graph,
|
|
44
|
+
)
|
|
45
|
+
from bw_processing.examples import examples_dir
|
|
46
|
+
from bw_processing.filesystem import clean_datapackage_name, md5, safe_filename
|
|
47
|
+
from bw_processing.indexing import reindex, reset_index
|
|
48
|
+
from bw_processing.io_helpers import generic_directory_filesystem, generic_zipfile_filesystem
|
|
49
|
+
from bw_processing.matrix_entry import MatrixEntry, MatrixName, create_datapackage_from_entries
|
|
50
|
+
from bw_processing.merging import merge_datapackages_with_mask
|
|
51
|
+
from bw_processing.proxies import UndefinedInterface
|
|
52
|
+
from bw_processing.unique_fields import as_unique_attributes, as_unique_attributes_dataframe
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import datetime
|
|
2
2
|
import uuid
|
|
3
|
+
import warnings
|
|
3
4
|
from abc import ABC
|
|
4
5
|
from functools import partial
|
|
5
|
-
from typing import Any, Dict, List, Optional, Union
|
|
6
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from bw_processing.matrix_entry import MatrixEntry
|
|
6
10
|
|
|
7
11
|
import numpy as np
|
|
8
12
|
import pandas as pd
|
|
@@ -11,7 +15,7 @@ from fsspec import AbstractFileSystem
|
|
|
11
15
|
# Use this instead of fsspec MemoryFileSystem because that is a singleton!?
|
|
12
16
|
from morefs.dict import DictFS
|
|
13
17
|
|
|
14
|
-
from .constants import (
|
|
18
|
+
from bw_processing.constants import (
|
|
15
19
|
DEFAULT_LICENSES,
|
|
16
20
|
INDICES_DTYPE,
|
|
17
21
|
MAX_SIGNED_32BIT_INT,
|
|
@@ -22,7 +26,7 @@ from .constants import (
|
|
|
22
26
|
PARQUET_SERIALIZE_FORMAT_NAME,
|
|
23
27
|
MatrixSerializeFormat,
|
|
24
28
|
)
|
|
25
|
-
from .errors import (
|
|
29
|
+
from bw_processing.errors import (
|
|
26
30
|
Closed,
|
|
27
31
|
InvalidMimetype,
|
|
28
32
|
LengthMismatch,
|
|
@@ -31,10 +35,10 @@ from .errors import (
|
|
|
31
35
|
ShapeMismatch,
|
|
32
36
|
WrongDatatype,
|
|
33
37
|
)
|
|
34
|
-
from .filesystem import clean_datapackage_name
|
|
35
|
-
from .io_helpers import file_reader, file_writer
|
|
36
|
-
from .proxies import Proxy, UndefinedInterface
|
|
37
|
-
from .utils import check_name, check_suffix, load_bytes, resolve_dict_iterator, utc_now
|
|
38
|
+
from bw_processing.filesystem import clean_datapackage_name
|
|
39
|
+
from bw_processing.io_helpers import file_reader, file_writer
|
|
40
|
+
from bw_processing.proxies import Proxy, UndefinedInterface
|
|
41
|
+
from bw_processing.utils import check_name, check_suffix, load_bytes, resolve_dict_iterator, utc_now
|
|
38
42
|
|
|
39
43
|
|
|
40
44
|
class DatapackageBase(ABC):
|
|
@@ -448,6 +452,30 @@ class Datapackage(DatapackageBase):
|
|
|
448
452
|
**kwargs,
|
|
449
453
|
)
|
|
450
454
|
|
|
455
|
+
def add_entries(
|
|
456
|
+
self,
|
|
457
|
+
*,
|
|
458
|
+
matrix: str,
|
|
459
|
+
entries: list["MatrixEntry"],
|
|
460
|
+
name: Optional[str] = None,
|
|
461
|
+
) -> None:
|
|
462
|
+
"""Add matrix data from a list of :class:`MatrixEntry` objects.
|
|
463
|
+
|
|
464
|
+
High-level convenience method that does not require working directly
|
|
465
|
+
with NumPy arrays.
|
|
466
|
+
|
|
467
|
+
Args:
|
|
468
|
+
matrix: Name of the target matrix (e.g. ``"technosphere"``).
|
|
469
|
+
entries: List of :class:`.MatrixEntry` instances.
|
|
470
|
+
name: Optional resource group name; auto-generated if omitted.
|
|
471
|
+
"""
|
|
472
|
+
self.add_persistent_vector_from_iterator(
|
|
473
|
+
matrix=matrix,
|
|
474
|
+
name=name,
|
|
475
|
+
dict_iterator=(e.as_dict() for e in entries),
|
|
476
|
+
nrows=len(entries),
|
|
477
|
+
)
|
|
478
|
+
|
|
451
479
|
def add_persistent_vector(
|
|
452
480
|
self,
|
|
453
481
|
*, # Forces use of keyword arguments
|
|
@@ -1091,6 +1119,10 @@ def load_datapackage(
|
|
|
1091
1119
|
def simple_graph(data: dict, fs: Optional[AbstractFileSystem] = None, **metadata) -> Datapackage:
|
|
1092
1120
|
"""Easy creation of simple datapackages with only persistent vectors.
|
|
1093
1121
|
|
|
1122
|
+
.. deprecated::
|
|
1123
|
+
Use :func:`bw_processing.matrix_entry.create_datapackage_from_entries` with
|
|
1124
|
+
:class:`bw_processing.matrix_entry.MatrixEntry` objects instead.
|
|
1125
|
+
|
|
1094
1126
|
Args:
|
|
1095
1127
|
* data: is a dictionary.
|
|
1096
1128
|
The data dictionary has the form::
|
|
@@ -1111,6 +1143,11 @@ def simple_graph(data: dict, fs: Optional[AbstractFileSystem] = None, **metadata
|
|
|
1111
1143
|
the datapackage.
|
|
1112
1144
|
|
|
1113
1145
|
"""
|
|
1146
|
+
warnings.warn(
|
|
1147
|
+
"simple_graph is deprecated; use create_datapackage_from_entries with MatrixEntry objects instead.",
|
|
1148
|
+
DeprecationWarning,
|
|
1149
|
+
stacklevel=2,
|
|
1150
|
+
)
|
|
1114
1151
|
dp = create_datapackage(fs=fs or DictFS(), **metadata)
|
|
1115
1152
|
for key, value in data.items():
|
|
1116
1153
|
indices_array = np.array([row[:2] for row in value], dtype=INDICES_DTYPE)
|
|
@@ -5,8 +5,8 @@ import numpy as np
|
|
|
5
5
|
import pandas as pd
|
|
6
6
|
from fsspec import AbstractFileSystem
|
|
7
7
|
|
|
8
|
-
from .datapackage import Datapackage, load_datapackage
|
|
9
|
-
from .errors import NonUnique
|
|
8
|
+
from bw_processing.datapackage import Datapackage, load_datapackage
|
|
9
|
+
from bw_processing.errors import NonUnique
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
def _get_csv_data(
|
|
@@ -11,12 +11,12 @@ from fsspec.implementations.local import LocalFileSystem
|
|
|
11
11
|
from fsspec.implementations.zip import ZipFileSystem
|
|
12
12
|
from morefs.dict import DictFS
|
|
13
13
|
|
|
14
|
-
from .constants import MatrixSerializeFormat
|
|
15
|
-
from .errors import InvalidMimetype
|
|
16
|
-
from .proxies import Proxy
|
|
14
|
+
from bw_processing.constants import MatrixSerializeFormat
|
|
15
|
+
from bw_processing.errors import InvalidMimetype
|
|
16
|
+
from bw_processing.proxies import Proxy
|
|
17
17
|
|
|
18
18
|
try:
|
|
19
|
-
from .io_parquet_helpers import load_ndarray_from_parquet, save_arr_to_parquet
|
|
19
|
+
from bw_processing.io_parquet_helpers import load_ndarray_from_parquet, save_arr_to_parquet
|
|
20
20
|
|
|
21
21
|
PARQUET = True
|
|
22
22
|
except ImportError:
|
|
@@ -13,8 +13,8 @@ import numpy
|
|
|
13
13
|
import numpy as np
|
|
14
14
|
import pyarrow.parquet as pq
|
|
15
15
|
|
|
16
|
-
from .errors import WrongDatatype
|
|
17
|
-
from .io_pyarrow_helpers import (
|
|
16
|
+
from bw_processing.errors import WrongDatatype
|
|
17
|
+
from bw_processing.io_pyarrow_helpers import (
|
|
18
18
|
numpy_distributions_vector_to_pyarrow_distributions_vector_table,
|
|
19
19
|
numpy_generic_matrix_to_pyarrow_generic_matrix_table,
|
|
20
20
|
numpy_generic_vector_to_pyarrow_generic_vector_table,
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import dataclasses
|
|
2
|
+
import math
|
|
3
|
+
from enum import Enum
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
from stats_arrays import NoUncertainty, UndefinedUncertainty
|
|
7
|
+
_NO_UNCERTAINTY_IDS = (UndefinedUncertainty.id, NoUncertainty.id)
|
|
8
|
+
except ImportError:
|
|
9
|
+
_NO_UNCERTAINTY_IDS = (0, 1)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class MatrixName(str, Enum):
|
|
13
|
+
"""Standard matrix names used in Brightway.
|
|
14
|
+
|
|
15
|
+
Because this is a ``str`` enum, members can be used anywhere a plain
|
|
16
|
+
string is accepted — no ``.value`` needed::
|
|
17
|
+
|
|
18
|
+
MatrixEntry(row=1, col=4, amount=2.5) # inside a dict keyed by MatrixName
|
|
19
|
+
dp.add_entries(matrix=MatrixName.technosphere, entries=[...])
|
|
20
|
+
|
|
21
|
+
Derived libraries may define additional matrices as plain strings;
|
|
22
|
+
these three cover the core Brightway LCA workflow.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
technosphere = "technosphere_matrix"
|
|
26
|
+
biosphere = "biosphere_matrix"
|
|
27
|
+
characterization = "characterization_matrix"
|
|
28
|
+
|
|
29
|
+
def __str__(self) -> str:
|
|
30
|
+
return self.value
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@dataclasses.dataclass(frozen=True)
|
|
34
|
+
class MatrixEntry:
|
|
35
|
+
"""A single entry destined for a matrix cell.
|
|
36
|
+
|
|
37
|
+
Multiple instances with the same (row, col) are summed during matrix
|
|
38
|
+
construction, so this is not necessarily the final cell value.
|
|
39
|
+
|
|
40
|
+
Field names and defaults match those expected by bw_processing's
|
|
41
|
+
``dictionary_formatter``. Convert to a plain dict with ``as_dict()``
|
|
42
|
+
before passing to bw_processing internals.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
row: Integer row index in the target matrix.
|
|
46
|
+
col: Integer column index in the target matrix.
|
|
47
|
+
amount: The numeric value to place at (row, col).
|
|
48
|
+
flip: If True, multiply the value by -1 when building the matrix.
|
|
49
|
+
uncertainty_type: Probability distribution type (0 = no uncertainty,
|
|
50
|
+
2 = lognormal, 3 = normal, etc. — see stats_arrays for full list).
|
|
51
|
+
loc: Distribution location parameter. For lognormal this is the log
|
|
52
|
+
of the median; defaults to NaN (no uncertainty).
|
|
53
|
+
scale: Distribution scale parameter (e.g. standard deviation).
|
|
54
|
+
shape: Distribution shape parameter.
|
|
55
|
+
minimum: Lower bound for distribution sampling.
|
|
56
|
+
maximum: Upper bound for distribution sampling.
|
|
57
|
+
negative: Whether the underlying value is negative.
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
row: int
|
|
61
|
+
col: int
|
|
62
|
+
amount: float
|
|
63
|
+
flip: bool = False
|
|
64
|
+
uncertainty_type: int = 0
|
|
65
|
+
loc: float = math.nan
|
|
66
|
+
scale: float = math.nan
|
|
67
|
+
shape: float = math.nan
|
|
68
|
+
minimum: float = math.nan
|
|
69
|
+
maximum: float = math.nan
|
|
70
|
+
negative: bool = False
|
|
71
|
+
|
|
72
|
+
def __post_init__(self):
|
|
73
|
+
if self.uncertainty_type in _NO_UNCERTAINTY_IDS:
|
|
74
|
+
if math.isnan(self.loc):
|
|
75
|
+
object.__setattr__(self, "loc", self.amount)
|
|
76
|
+
elif self.loc != self.amount:
|
|
77
|
+
raise ValueError(
|
|
78
|
+
f"uncertainty_type {self.uncertainty_type} requires loc == amount, "
|
|
79
|
+
f"got loc={self.loc} but amount={self.amount}"
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
def as_dict(self) -> dict:
|
|
83
|
+
return dataclasses.asdict(self)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def create_datapackage_from_entries(
|
|
87
|
+
data: dict,
|
|
88
|
+
fs=None,
|
|
89
|
+
**metadata,
|
|
90
|
+
):
|
|
91
|
+
"""Create a datapackage from a dictionary of :class:`MatrixEntry` lists.
|
|
92
|
+
|
|
93
|
+
This is the recommended high-level entry point for building datapackages
|
|
94
|
+
without working directly with NumPy arrays.
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
data: Dictionary mapping matrix names to lists of :class:`MatrixEntry`
|
|
98
|
+
objects. Use :class:`MatrixName` members as keys for the standard
|
|
99
|
+
Brightway matrices; derived libraries may use plain strings for
|
|
100
|
+
additional matrices::
|
|
101
|
+
|
|
102
|
+
{
|
|
103
|
+
MatrixName.technosphere: [
|
|
104
|
+
MatrixEntry(row=1, col=4, amount=2.5),
|
|
105
|
+
MatrixEntry(row=2, col=5, amount=7.0, flip=True),
|
|
106
|
+
],
|
|
107
|
+
MatrixName.biosphere: [
|
|
108
|
+
MatrixEntry(row=10, col=4, amount=0.3),
|
|
109
|
+
],
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
fs: Optional filesystem. Defaults to an in-memory filesystem.
|
|
113
|
+
**metadata: Additional keyword arguments passed to
|
|
114
|
+
:func:`create_datapackage` (e.g. ``name``, ``id_``).
|
|
115
|
+
|
|
116
|
+
Returns:
|
|
117
|
+
A :class:`Datapackage` instance.
|
|
118
|
+
"""
|
|
119
|
+
from bw_processing.datapackage import create_datapackage
|
|
120
|
+
|
|
121
|
+
dp = create_datapackage(fs=fs, **metadata)
|
|
122
|
+
for matrix_name, entries in data.items():
|
|
123
|
+
dp.add_entries(
|
|
124
|
+
matrix=matrix_name,
|
|
125
|
+
entries=entries,
|
|
126
|
+
name=f"{matrix_name}-data",
|
|
127
|
+
)
|
|
128
|
+
return dp
|
|
@@ -7,9 +7,9 @@ import pandas as pd
|
|
|
7
7
|
from fsspec import AbstractFileSystem
|
|
8
8
|
from morefs.dict import DictFS
|
|
9
9
|
|
|
10
|
-
from .datapackage import DatapackageBase, create_datapackage
|
|
11
|
-
from .errors import LengthMismatch
|
|
12
|
-
from .io_helpers import file_writer
|
|
10
|
+
from bw_processing.datapackage import DatapackageBase, create_datapackage
|
|
11
|
+
from bw_processing.errors import LengthMismatch
|
|
12
|
+
from bw_processing.io_helpers import file_writer
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
def mask_resource(obj: Any, mask: np.ndarray) -> Any:
|
|
@@ -6,9 +6,9 @@ from typing import Any, Union
|
|
|
6
6
|
import numpy as np
|
|
7
7
|
from numpy.lib.recfunctions import repack_fields
|
|
8
8
|
|
|
9
|
-
from .array_creation import create_structured_array
|
|
10
|
-
from .constants import INDICES_DTYPE, NAME_RE, UNCERTAINTY_DTYPE
|
|
11
|
-
from .errors import InvalidName
|
|
9
|
+
from bw_processing.array_creation import create_structured_array
|
|
10
|
+
from bw_processing.constants import INDICES_DTYPE, NAME_RE, UNCERTAINTY_DTYPE
|
|
11
|
+
from bw_processing.errors import InvalidName
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
def load_bytes(obj: Any) -> Any:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: bw_processing
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.1.1
|
|
4
4
|
Summary: Foo
|
|
5
5
|
Author-email: Chris Mutel <cmutel@gmail.com>
|
|
6
6
|
Maintainer-email: Chris Mutel <cmutel@gmail.com>
|
|
@@ -38,6 +38,7 @@ Requires-Dist: pytest; extra == "dev"
|
|
|
38
38
|
Requires-Dist: pytest-cov; extra == "dev"
|
|
39
39
|
Requires-Dist: pytest-randomly; extra == "dev"
|
|
40
40
|
Requires-Dist: setuptools; extra == "dev"
|
|
41
|
+
Dynamic: license-file
|
|
41
42
|
|
|
42
43
|
# bw-processing
|
|
43
44
|
|
|
@@ -81,7 +82,7 @@ The [Brightway LCA framework](https://brightway.dev/) has stored data used in co
|
|
|
81
82
|
* **Support for vector and array data**. Vector (i.e. only one possible value per input) and array (i.e. many possible values, also called presamples) data are now both natively supported in data packages.
|
|
82
83
|
* **Portability**. Processed arrays can include metadata that allows for reindexing on other machines, so that processed arrays can be distributed and reused. Before, this was not possible, as integer IDs were randomly assigned on each computer, and would be different from machine to machine or even across Brightway projects.
|
|
83
84
|
* **Dynamic data sources**. Instead of requiring that data for matrix construction be present and savedd on disk, it can now be generated dynamically, either through code running locally or on another computer system. This is a big step towards embeddding life cycle assessment in a web of environmental models.
|
|
84
|
-
* **Use [
|
|
85
|
+
* **Use [fsspec](https://filesystem-spec.readthedocs.io/en/latest/) for file IO**. The use of this library allows for data packages to be stored on your local computer, or on [many logical or virtual file systems](https://docs.pyfilesystem.org/en/latest/guide.html).
|
|
85
86
|
* **Simpler handling of numeric values whose sign should be flipped**. Sometimes it is more convenient to specify positive numbers in dataset definitions, even though such numbers should be negative when inserted into the resulting matrices. For example, in the technosphere matrix in life cycle assessment, products produced are positive and products consumed are negative, though both values are given as positive in datasets. Brightway used to use a type mapping dictionary to indicate which values in a matrix should have their sign flipped after insertion. Such mapping dictionaries are brittle and inelegant. `bw_processing` uses an optional boolean vector, called `flip`, to indicate if any values should be flipped.
|
|
86
87
|
* **Separation of uncertainty distribution parameters from other data**. Fitting data to a [probability density function](https://en.wikipedia.org/wiki/Probability_density_function) (PDF), or an estimate of such a PDF, is only one approach to quantitative uncertainty analysis. We would like to support other approaches, including [direct sampling from real data](https://github.com/PascalLesage/presamples/). Therefore, uncertainty distribution parameters are stored separately, only loaded if needed, and are only one way to express quantitative uncertainty.
|
|
87
88
|
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
MANIFEST.in
|
|
3
|
+
README.md
|
|
4
|
+
pyproject.toml
|
|
5
|
+
src/bw_processing/__init__.py
|
|
6
|
+
src/bw_processing/array_creation.py
|
|
7
|
+
src/bw_processing/constants.py
|
|
8
|
+
src/bw_processing/datapackage.py
|
|
9
|
+
src/bw_processing/errors.py
|
|
10
|
+
src/bw_processing/filesystem.py
|
|
11
|
+
src/bw_processing/indexing.py
|
|
12
|
+
src/bw_processing/io_helpers.py
|
|
13
|
+
src/bw_processing/io_parquet_helpers.py
|
|
14
|
+
src/bw_processing/io_pyarrow_helpers.py
|
|
15
|
+
src/bw_processing/matrix_entry.py
|
|
16
|
+
src/bw_processing/merging.py
|
|
17
|
+
src/bw_processing/proxies.py
|
|
18
|
+
src/bw_processing/unique_fields.py
|
|
19
|
+
src/bw_processing/utils.py
|
|
20
|
+
src/bw_processing.egg-info/PKG-INFO
|
|
21
|
+
src/bw_processing.egg-info/SOURCES.txt
|
|
22
|
+
src/bw_processing.egg-info/dependency_links.txt
|
|
23
|
+
src/bw_processing.egg-info/requires.txt
|
|
24
|
+
src/bw_processing.egg-info/top_level.txt
|
|
25
|
+
src/bw_processing/examples/__init__.py
|
|
26
|
+
src/bw_processing/examples/datapackage_2.zip
|
|
27
|
+
src/bw_processing/examples/interfaces.py
|
|
28
|
+
src/bw_processing/examples/parquet_files.py
|
|
29
|
+
src/bw_processing/examples/simple.zip
|
|
30
|
+
src/bw_processing/examples/datapackage_1/another name.indices.parquet
|
|
31
|
+
src/bw_processing/examples/datapackage_1/sa-data-vector-from-dict.data.parquet
|
|
32
|
+
src/bw_processing/examples/datapackage_1/sa-data-vector-from-dict.distributions.parquet
|
|
33
|
+
src/bw_processing/examples/datapackage_1/sa-data-vector-from-dict.flip.parquet
|
|
34
|
+
src/bw_processing/examples/datapackage_1/sa-data-vector-from-dict.indices.parquet
|
|
35
|
+
src/bw_processing/examples/datapackage_1/some name.data.parquet
|
|
36
|
+
src/bw_processing/examples/datapackage_1/some name.flip.parquet
|
|
37
|
+
src/bw_processing/examples/datapackage_1/some name.indices.parquet
|
|
38
|
+
tests/test_array_creation.py
|
|
39
|
+
tests/test_datapackage.py
|
|
40
|
+
tests/test_filesystem.py
|
|
41
|
+
tests/test_filtered_datapackage.py
|
|
42
|
+
tests/test_indexing.py
|
|
43
|
+
tests/test_integration.py
|
|
44
|
+
tests/test_interfaces.py
|
|
45
|
+
tests/test_io_parquet_helpers.py
|
|
46
|
+
tests/test_io_pyarrow_helpers.py
|
|
47
|
+
tests/test_loading.py
|
|
48
|
+
tests/test_matrix_entry.py
|
|
49
|
+
tests/test_merging.py
|
|
50
|
+
tests/test_proxies.py
|
|
51
|
+
tests/test_unique_fields.py
|
|
52
|
+
tests/test_utils.py
|
|
@@ -59,11 +59,8 @@ def test_save_load_parquet_file_data_matrix(dtype, tmp_path_factory):
|
|
|
59
59
|
arr = data_matrix(dtype=dtype)
|
|
60
60
|
file = tmp_path_factory.mktemp("data") / "data_matrix.parquet"
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
with file as fp:
|
|
66
|
-
loaded_arr = load_ndarray_from_parquet(fp)
|
|
62
|
+
save_arr_to_parquet(file=file, arr=arr, meta_object="matrix", meta_type="generic")
|
|
63
|
+
loaded_arr = load_ndarray_from_parquet(file)
|
|
67
64
|
|
|
68
65
|
assert arr.dtype == loaded_arr.dtype and np.array_equal(arr, loaded_arr)
|
|
69
66
|
|
|
@@ -74,11 +71,8 @@ def test_save_load_parquet_file_distribution_vector(distributions_vector, tmp_pa
|
|
|
74
71
|
arr = distributions_vector
|
|
75
72
|
file = tmp_path_factory.mktemp("data") / "distributions_vector.parquet"
|
|
76
73
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
with file as fp:
|
|
81
|
-
loaded_arr = load_ndarray_from_parquet(fp)
|
|
74
|
+
save_arr_to_parquet(file=file, arr=arr, meta_object="vector", meta_type="distributions")
|
|
75
|
+
loaded_arr = load_ndarray_from_parquet(file)
|
|
82
76
|
|
|
83
77
|
assert vector_equal_with_uncertainty_dtype(arr, loaded_arr)
|
|
84
78
|
|
|
@@ -88,25 +82,21 @@ def test_save_load_parquet_file_wrong_meta_object(indices_vector, tmp_path_facto
|
|
|
88
82
|
file = tmp_path_factory.mktemp("data") / "indices_vector.parquet"
|
|
89
83
|
|
|
90
84
|
with pytest.raises(NotImplementedError):
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
)
|
|
85
|
+
save_arr_to_parquet(
|
|
86
|
+
file=file, arr=indices_vector, meta_object="wrong", meta_type="indices"
|
|
87
|
+
)
|
|
95
88
|
|
|
96
89
|
with pytest.raises(NotImplementedError):
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
)
|
|
90
|
+
save_arr_to_parquet(
|
|
91
|
+
file=file, arr=indices_vector, meta_object="vector", meta_type="indices"
|
|
92
|
+
)
|
|
101
93
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
pq.write_table(new_table, fp)
|
|
94
|
+
table = pq.read_table(file)
|
|
95
|
+
metadata = {"object": "wrong", "type": "indices"}
|
|
96
|
+
new_table = table.replace_schema_metadata(metadata=metadata)
|
|
97
|
+
pq.write_table(new_table, file)
|
|
107
98
|
|
|
108
|
-
|
|
109
|
-
load_ndarray_from_parquet(fp)
|
|
99
|
+
load_ndarray_from_parquet(file)
|
|
110
100
|
|
|
111
101
|
|
|
112
102
|
@pytest.mark.skipif(sys.version_info[:2] == (3, 8), reason="Doesn't work in CI filesystem")
|
|
@@ -114,25 +104,21 @@ def test_save_load_parquet_file_wrong_meta_type(indices_vector, tmp_path_factory
|
|
|
114
104
|
file = tmp_path_factory.mktemp("data") / "indices_vector.parquet"
|
|
115
105
|
|
|
116
106
|
with pytest.raises(NotImplementedError):
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
)
|
|
107
|
+
save_arr_to_parquet(
|
|
108
|
+
file=file, arr=indices_vector, meta_object="vector", meta_type="wrong"
|
|
109
|
+
)
|
|
121
110
|
|
|
122
111
|
with pytest.raises(NotImplementedError):
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
)
|
|
112
|
+
save_arr_to_parquet(
|
|
113
|
+
file=file, arr=indices_vector, meta_object="vector", meta_type="indices"
|
|
114
|
+
)
|
|
127
115
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
pq.write_table(new_table, fp)
|
|
116
|
+
table = pq.read_table(file)
|
|
117
|
+
metadata = {"object": "vector", "type": "wrong"}
|
|
118
|
+
new_table = table.replace_schema_metadata(metadata=metadata)
|
|
119
|
+
pq.write_table(new_table, file)
|
|
133
120
|
|
|
134
|
-
|
|
135
|
-
load_ndarray_from_parquet(fp)
|
|
121
|
+
load_ndarray_from_parquet(file)
|
|
136
122
|
|
|
137
123
|
|
|
138
124
|
@pytest.mark.skipif(sys.version_info[:2] == (3, 8), reason="Doesn't work in CI filesystem")
|
|
@@ -140,16 +126,13 @@ def test_save_load_parquet_file_wrong_metadata_format(indices_vector, tmp_path_f
|
|
|
140
126
|
file = tmp_path_factory.mktemp("data") / "indices_vector.parquet"
|
|
141
127
|
|
|
142
128
|
with pytest.raises(WrongDatatype):
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
with file as fp:
|
|
155
|
-
load_ndarray_from_parquet(fp)
|
|
129
|
+
save_arr_to_parquet(
|
|
130
|
+
file=file, arr=indices_vector, meta_object="vector", meta_type="indices"
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
table = pq.read_table(file)
|
|
134
|
+
metadata = {}
|
|
135
|
+
new_table = table.replace_schema_metadata(metadata=metadata)
|
|
136
|
+
pq.write_table(new_table, file)
|
|
137
|
+
|
|
138
|
+
load_ndarray_from_parquet(file)
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import math
|
|
2
|
+
import warnings
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
from bw_processing import (
|
|
8
|
+
MatrixEntry,
|
|
9
|
+
MatrixName,
|
|
10
|
+
create_datapackage_from_entries,
|
|
11
|
+
simple_graph,
|
|
12
|
+
)
|
|
13
|
+
from bw_processing.constants import UNCERTAINTY_DTYPE
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class TestMatrixName:
|
|
17
|
+
def test_values(self):
|
|
18
|
+
assert MatrixName.technosphere == "technosphere_matrix"
|
|
19
|
+
assert MatrixName.biosphere == "biosphere_matrix"
|
|
20
|
+
assert MatrixName.characterization == "characterization_matrix"
|
|
21
|
+
|
|
22
|
+
def test_str(self):
|
|
23
|
+
assert str(MatrixName.technosphere) == "technosphere_matrix"
|
|
24
|
+
|
|
25
|
+
def test_fstring(self):
|
|
26
|
+
assert f"{MatrixName.biosphere}" == "biosphere_matrix"
|
|
27
|
+
|
|
28
|
+
def test_usable_as_dict_key(self):
|
|
29
|
+
d = {MatrixName.technosphere: [1, 2, 3]}
|
|
30
|
+
assert d["technosphere_matrix"] == [1, 2, 3]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class TestMatrixEntry:
|
|
34
|
+
def test_required_fields(self):
|
|
35
|
+
e = MatrixEntry(row=1, col=2, amount=3.0)
|
|
36
|
+
assert e.row == 1
|
|
37
|
+
assert e.col == 2
|
|
38
|
+
assert e.amount == 3.0
|
|
39
|
+
|
|
40
|
+
def test_defaults(self):
|
|
41
|
+
e = MatrixEntry(row=1, col=2, amount=3.0)
|
|
42
|
+
assert e.flip is False
|
|
43
|
+
assert e.uncertainty_type == 0
|
|
44
|
+
assert e.negative is False
|
|
45
|
+
assert e.loc == pytest.approx(3.0)
|
|
46
|
+
assert math.isnan(e.scale)
|
|
47
|
+
assert math.isnan(e.shape)
|
|
48
|
+
assert math.isnan(e.minimum)
|
|
49
|
+
assert math.isnan(e.maximum)
|
|
50
|
+
|
|
51
|
+
def test_loc_set_to_amount_for_no_uncertainty(self):
|
|
52
|
+
e = MatrixEntry(row=1, col=2, amount=5.0)
|
|
53
|
+
assert e.loc == pytest.approx(5.0)
|
|
54
|
+
|
|
55
|
+
def test_explicit_loc_matching_amount_accepted(self):
|
|
56
|
+
e = MatrixEntry(row=1, col=2, amount=5.0, uncertainty_type=0, loc=5.0)
|
|
57
|
+
assert e.loc == pytest.approx(5.0)
|
|
58
|
+
|
|
59
|
+
def test_loc_mismatch_raises_for_uncertainty_type_0(self):
|
|
60
|
+
with pytest.raises(ValueError, match="loc == amount"):
|
|
61
|
+
MatrixEntry(row=1, col=2, amount=5.0, uncertainty_type=0, loc=9.9)
|
|
62
|
+
|
|
63
|
+
def test_loc_mismatch_raises_for_uncertainty_type_1(self):
|
|
64
|
+
with pytest.raises(ValueError, match="loc == amount"):
|
|
65
|
+
MatrixEntry(row=1, col=2, amount=5.0, uncertainty_type=1, loc=9.9)
|
|
66
|
+
|
|
67
|
+
def test_loc_not_set_when_uncertainty_type_nonzero(self):
|
|
68
|
+
e = MatrixEntry(row=1, col=2, amount=5.0, uncertainty_type=2)
|
|
69
|
+
assert math.isnan(e.loc)
|
|
70
|
+
|
|
71
|
+
def test_frozen(self):
|
|
72
|
+
e = MatrixEntry(row=1, col=2, amount=3.0)
|
|
73
|
+
with pytest.raises(Exception):
|
|
74
|
+
e.amount = 99.0
|
|
75
|
+
|
|
76
|
+
def test_as_dict_keys(self):
|
|
77
|
+
e = MatrixEntry(row=1, col=2, amount=3.0)
|
|
78
|
+
d = e.as_dict()
|
|
79
|
+
assert set(d.keys()) == {
|
|
80
|
+
"row", "col", "amount", "flip", "uncertainty_type",
|
|
81
|
+
"loc", "scale", "shape", "minimum", "maximum", "negative",
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
def test_as_dict_values(self):
|
|
85
|
+
e = MatrixEntry(row=5, col=10, amount=2.5, flip=True, uncertainty_type=2,
|
|
86
|
+
loc=0.9, scale=0.1, negative=True)
|
|
87
|
+
d = e.as_dict()
|
|
88
|
+
assert d["row"] == 5
|
|
89
|
+
assert d["col"] == 10
|
|
90
|
+
assert d["amount"] == 2.5
|
|
91
|
+
assert d["flip"] is True
|
|
92
|
+
assert d["uncertainty_type"] == 2
|
|
93
|
+
assert d["loc"] == pytest.approx(0.9)
|
|
94
|
+
assert d["scale"] == pytest.approx(0.1)
|
|
95
|
+
assert d["negative"] is True
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class TestCreateDatapackageFromEntries:
|
|
99
|
+
def test_basic(self):
|
|
100
|
+
entries = [
|
|
101
|
+
MatrixEntry(row=1, col=4, amount=2.0),
|
|
102
|
+
MatrixEntry(row=2, col=5, amount=7.0),
|
|
103
|
+
]
|
|
104
|
+
dp = create_datapackage_from_entries({MatrixName.technosphere: entries})
|
|
105
|
+
assert "technosphere_matrix-data" in dp.groups
|
|
106
|
+
|
|
107
|
+
def test_multiple_matrices(self):
|
|
108
|
+
dp = create_datapackage_from_entries({
|
|
109
|
+
MatrixName.technosphere: [MatrixEntry(row=1, col=2, amount=1.0)],
|
|
110
|
+
MatrixName.biosphere: [MatrixEntry(row=3, col=4, amount=0.5)],
|
|
111
|
+
})
|
|
112
|
+
groups = list(dp.groups.keys())
|
|
113
|
+
assert "technosphere_matrix-data" in groups
|
|
114
|
+
assert "biosphere_matrix-data" in groups
|
|
115
|
+
|
|
116
|
+
def test_plain_string_matrix_name(self):
|
|
117
|
+
dp = create_datapackage_from_entries({
|
|
118
|
+
"custom_matrix": [MatrixEntry(row=1, col=2, amount=1.0)],
|
|
119
|
+
})
|
|
120
|
+
assert "custom_matrix-data" in dp.groups
|
|
121
|
+
|
|
122
|
+
def test_data_values(self):
|
|
123
|
+
entries = [
|
|
124
|
+
MatrixEntry(row=1, col=4, amount=2.0),
|
|
125
|
+
MatrixEntry(row=2, col=5, amount=7.0),
|
|
126
|
+
MatrixEntry(row=3, col=6, amount=12.0),
|
|
127
|
+
]
|
|
128
|
+
dp = create_datapackage_from_entries({MatrixName.technosphere: entries})
|
|
129
|
+
group = dp.groups["technosphere_matrix-data"]
|
|
130
|
+
|
|
131
|
+
data_resource = next(r for r in group.resources if r["kind"] == "data")
|
|
132
|
+
data_idx = dp.resources.index(data_resource)
|
|
133
|
+
data = dp.data[data_idx]
|
|
134
|
+
assert set(data) == {2.0, 7.0, 12.0}
|
|
135
|
+
|
|
136
|
+
def test_flip_stored(self):
|
|
137
|
+
entries = [
|
|
138
|
+
MatrixEntry(row=1, col=4, amount=2.0, flip=True),
|
|
139
|
+
MatrixEntry(row=2, col=5, amount=7.0, flip=False),
|
|
140
|
+
]
|
|
141
|
+
dp = create_datapackage_from_entries({MatrixName.technosphere: entries})
|
|
142
|
+
group = dp.groups["technosphere_matrix-data"]
|
|
143
|
+
|
|
144
|
+
flip_resource = next(r for r in group.resources if r["kind"] == "flip")
|
|
145
|
+
flip_idx = dp.resources.index(flip_resource)
|
|
146
|
+
flip = dp.data[flip_idx]
|
|
147
|
+
assert flip.sum() == 1
|
|
148
|
+
|
|
149
|
+
def test_uncertainty_stored(self):
|
|
150
|
+
entries = [
|
|
151
|
+
MatrixEntry(row=1, col=4, amount=2.0, uncertainty_type=2, loc=0.7, scale=0.1),
|
|
152
|
+
MatrixEntry(row=2, col=5, amount=7.0),
|
|
153
|
+
]
|
|
154
|
+
dp = create_datapackage_from_entries({MatrixName.technosphere: entries})
|
|
155
|
+
group = dp.groups["technosphere_matrix-data"]
|
|
156
|
+
|
|
157
|
+
dist_resource = next(r for r in group.resources if r["kind"] == "distributions")
|
|
158
|
+
dist_idx = dp.resources.index(dist_resource)
|
|
159
|
+
dist = dp.data[dist_idx]
|
|
160
|
+
assert dist.dtype == np.dtype(UNCERTAINTY_DTYPE)
|
|
161
|
+
uncertainty_types = set(dist["uncertainty_type"])
|
|
162
|
+
assert 2 in uncertainty_types
|
|
163
|
+
|
|
164
|
+
def test_metadata_passed_through(self):
|
|
165
|
+
dp = create_datapackage_from_entries(
|
|
166
|
+
{MatrixName.technosphere: [MatrixEntry(row=1, col=2, amount=1.0)]},
|
|
167
|
+
name="my-package",
|
|
168
|
+
)
|
|
169
|
+
assert dp.metadata["name"] == "my-package"
|
|
170
|
+
|
|
171
|
+
class TestSimpleGraphDeprecation:
|
|
172
|
+
def test_deprecation_warning(self):
|
|
173
|
+
with warnings.catch_warnings(record=True) as w:
|
|
174
|
+
warnings.simplefilter("always")
|
|
175
|
+
simple_graph({"technosphere": [(1, 4, 2.5)]})
|
|
176
|
+
assert len(w) == 1
|
|
177
|
+
assert issubclass(w[0].category, DeprecationWarning)
|
|
178
|
+
assert "create_datapackage_from_entries" in str(w[0].message)
|
bw_processing-1.0/MANIFEST.in
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
__all__ = (
|
|
2
|
-
"__version__",
|
|
3
|
-
"as_unique_attributes",
|
|
4
|
-
"as_unique_attributes_dataframe",
|
|
5
|
-
"clean_datapackage_name",
|
|
6
|
-
"create_array",
|
|
7
|
-
"create_datapackage",
|
|
8
|
-
"create_structured_array",
|
|
9
|
-
"Datapackage",
|
|
10
|
-
"DatapackageBase",
|
|
11
|
-
"DEFAULT_LICENSES",
|
|
12
|
-
"examples_dir",
|
|
13
|
-
"FilteredDatapackage",
|
|
14
|
-
"generic_directory_filesystem",
|
|
15
|
-
"generic_zipfile_filesystem",
|
|
16
|
-
"INDICES_DTYPE",
|
|
17
|
-
"load_datapackage",
|
|
18
|
-
"MatrixSerializeFormat",
|
|
19
|
-
"md5",
|
|
20
|
-
"merge_datapackages_with_mask",
|
|
21
|
-
"reindex",
|
|
22
|
-
"reset_index",
|
|
23
|
-
"safe_filename",
|
|
24
|
-
"simple_graph",
|
|
25
|
-
"UNCERTAINTY_DTYPE",
|
|
26
|
-
"UndefinedInterface",
|
|
27
|
-
)
|
|
28
|
-
|
|
29
|
-
__version__ = "1.0"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
from .array_creation import create_array, create_structured_array
|
|
33
|
-
from .constants import DEFAULT_LICENSES, INDICES_DTYPE, UNCERTAINTY_DTYPE, MatrixSerializeFormat
|
|
34
|
-
from .datapackage import (
|
|
35
|
-
Datapackage,
|
|
36
|
-
DatapackageBase,
|
|
37
|
-
FilteredDatapackage,
|
|
38
|
-
create_datapackage,
|
|
39
|
-
load_datapackage,
|
|
40
|
-
simple_graph,
|
|
41
|
-
)
|
|
42
|
-
from .examples import examples_dir
|
|
43
|
-
from .filesystem import clean_datapackage_name, md5, safe_filename
|
|
44
|
-
from .indexing import reindex, reset_index
|
|
45
|
-
from .io_helpers import generic_directory_filesystem, generic_zipfile_filesystem
|
|
46
|
-
from .merging import merge_datapackages_with_mask
|
|
47
|
-
from .proxies import UndefinedInterface
|
|
48
|
-
from .unique_fields import as_unique_attributes, as_unique_attributes_dataframe
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
LICENSE
|
|
2
|
-
MANIFEST.in
|
|
3
|
-
README.md
|
|
4
|
-
pyproject.toml
|
|
5
|
-
bw_processing/__init__.py
|
|
6
|
-
bw_processing/array_creation.py
|
|
7
|
-
bw_processing/constants.py
|
|
8
|
-
bw_processing/datapackage.py
|
|
9
|
-
bw_processing/errors.py
|
|
10
|
-
bw_processing/filesystem.py
|
|
11
|
-
bw_processing/indexing.py
|
|
12
|
-
bw_processing/io_helpers.py
|
|
13
|
-
bw_processing/io_parquet_helpers.py
|
|
14
|
-
bw_processing/io_pyarrow_helpers.py
|
|
15
|
-
bw_processing/merging.py
|
|
16
|
-
bw_processing/proxies.py
|
|
17
|
-
bw_processing/unique_fields.py
|
|
18
|
-
bw_processing/utils.py
|
|
19
|
-
bw_processing.egg-info/PKG-INFO
|
|
20
|
-
bw_processing.egg-info/SOURCES.txt
|
|
21
|
-
bw_processing.egg-info/dependency_links.txt
|
|
22
|
-
bw_processing.egg-info/requires.txt
|
|
23
|
-
bw_processing.egg-info/top_level.txt
|
|
24
|
-
bw_processing/examples/__init__.py
|
|
25
|
-
bw_processing/examples/datapackage_2.zip
|
|
26
|
-
bw_processing/examples/interfaces.py
|
|
27
|
-
bw_processing/examples/parquet_files.py
|
|
28
|
-
bw_processing/examples/simple.zip
|
|
29
|
-
bw_processing/examples/datapackage_1/another name.indices.parquet
|
|
30
|
-
bw_processing/examples/datapackage_1/sa-data-vector-from-dict.data.parquet
|
|
31
|
-
bw_processing/examples/datapackage_1/sa-data-vector-from-dict.distributions.parquet
|
|
32
|
-
bw_processing/examples/datapackage_1/sa-data-vector-from-dict.flip.parquet
|
|
33
|
-
bw_processing/examples/datapackage_1/sa-data-vector-from-dict.indices.parquet
|
|
34
|
-
bw_processing/examples/datapackage_1/some name.data.parquet
|
|
35
|
-
bw_processing/examples/datapackage_1/some name.flip.parquet
|
|
36
|
-
bw_processing/examples/datapackage_1/some name.indices.parquet
|
|
37
|
-
tests/test_array_creation.py
|
|
38
|
-
tests/test_datapackage.py
|
|
39
|
-
tests/test_filesystem.py
|
|
40
|
-
tests/test_filtered_datapackage.py
|
|
41
|
-
tests/test_indexing.py
|
|
42
|
-
tests/test_integration.py
|
|
43
|
-
tests/test_interfaces.py
|
|
44
|
-
tests/test_io_parquet_helpers.py
|
|
45
|
-
tests/test_io_pyarrow_helpers.py
|
|
46
|
-
tests/test_loading.py
|
|
47
|
-
tests/test_merging.py
|
|
48
|
-
tests/test_proxies.py
|
|
49
|
-
tests/test_unique_fields.py
|
|
50
|
-
tests/test_utils.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|