matrix-utils 0.4.3__tar.gz → 0.6__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.
- {matrix_utils-0.4.3 → matrix_utils-0.6}/CHANGELOG.md +8 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/PKG-INFO +3 -3
- {matrix_utils-0.4.3 → matrix_utils-0.6}/dev/Mapping speed tests.ipynb +129 -21
- {matrix_utils-0.4.3 → matrix_utils-0.6}/matrix_utils/__init__.py +1 -1
- {matrix_utils-0.4.3 → matrix_utils-0.6}/matrix_utils/array_mapper.py +27 -14
- {matrix_utils-0.4.3 → matrix_utils-0.6}/matrix_utils/indexers.py +10 -2
- {matrix_utils-0.4.3 → matrix_utils-0.6}/matrix_utils/mapped_matrix.py +11 -5
- {matrix_utils-0.4.3 → matrix_utils-0.6}/matrix_utils/mapped_matrix_dict.py +2 -2
- {matrix_utils-0.4.3 → matrix_utils-0.6}/matrix_utils/resource_group.py +3 -1
- {matrix_utils-0.4.3 → matrix_utils-0.6}/matrix_utils.egg-info/PKG-INFO +3 -3
- {matrix_utils-0.4.3 → matrix_utils-0.6}/matrix_utils.egg-info/requires.txt +2 -2
- {matrix_utils-0.4.3 → matrix_utils-0.6}/pyproject.toml +2 -2
- {matrix_utils-0.4.3 → matrix_utils-0.6}/tests/array_mapper.py +10 -2
- {matrix_utils-0.4.3 → matrix_utils-0.6}/tests/fixtures/basic.py +23 -11
- {matrix_utils-0.4.3 → matrix_utils-0.6}/tests/fixtures/create_static_fixtures.py +4 -4
- {matrix_utils-0.4.3 → matrix_utils-0.6}/tests/indexers.py +12 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/tests/integration.py +39 -15
- {matrix_utils-0.4.3 → matrix_utils-0.6}/tests/mapped_matrix.py +36 -37
- {matrix_utils-0.4.3 → matrix_utils-0.6}/tests/monte_carlo.py +0 -2
- {matrix_utils-0.4.3 → matrix_utils-0.6}/tests/ordering.py +0 -1
- {matrix_utils-0.4.3 → matrix_utils-0.6}/tests/utils.py +1 -1
- {matrix_utils-0.4.3 → matrix_utils-0.6}/.gitignore +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/.pre-commit-config.yaml +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/CODE_OF_CONDUCT.md +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/LICENSE +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/MANIFEST.in +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/README.md +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/binder/Brightway 2.5 demonstration.ipynb +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/binder/environment.yml +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/dev/Brightway 2.5 - Linking with IAMs.ipynb +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/dev/Brightway 2.5 demonstration.ipynb +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/dev/Graph traversal with modification.ipynb +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/dev/Indexing speed tests.ipynb +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/dev/Interfaces which produce results for multiple matrices.ipynb +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/dev/Multifunctionality with Brightway 2.5.ipynb +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/dev/Real-time modification of hybrid databases.ipynb +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/dev/Supply chain modification.ipynb +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/dev/Untitled.ipynb +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/dev/profiling/bw2.prof +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/dev/profiling/bw2.svg +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/dev/profiling/bw25.prof +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/dev/profiling/bw25.svg +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/dev/profiling/bw25_profile.txt +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/dev/profiling/bw25_profiling.py +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/dev/profiling/bw2_profile.txt +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/dev/profiling/bw2_profiling.py +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/dev/profiling/profiling-versus-bw2.py +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/dev/speed_test_unique_indices.py +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/dev/speed_tests.py +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/docs/Makefile +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/docs/conf.py +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/docs/index.rst +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/docs/loading.rst +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/docs/make.bat +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/docs/saving.rst +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/docs/utilities.rst +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/matrix_utils/aggregation.py +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/matrix_utils/errors.py +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/matrix_utils/utils.py +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/matrix_utils.egg-info/SOURCES.txt +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/matrix_utils.egg-info/dependency_links.txt +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/matrix_utils.egg-info/top_level.txt +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/setup.cfg +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/tests/fixtures/__init__.py +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/tests/fixtures/a-first.zip +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/tests/fixtures/b-second.zip +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/tests/fixtures/sa-1.zip +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/tests/fixtures/sa-2.zip +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/tests/interfaces.py +0 -0
- {matrix_utils-0.4.3 → matrix_utils-0.6}/tests/masking.py +0 -0
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
### [0.6] - 2024-11-01
|
|
4
|
+
|
|
5
|
+
* New array mapping implementation using sparse matrices which is ~100x faster and allows for very large input values
|
|
6
|
+
|
|
7
|
+
### [0.5] - 2024-08-20
|
|
8
|
+
|
|
9
|
+
* Default is now 64 bit integers for indexing; compatible with `bw_processing` 1.0
|
|
10
|
+
|
|
3
11
|
### [0.4.3] - 2024-06-04
|
|
4
12
|
|
|
5
13
|
* Allow `MappedMatrixDict` to take extra `kwargs` for compatiblity with custom matrix classes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: matrix_utils
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6
|
|
4
4
|
Summary: Tools to create matrices from data packages
|
|
5
5
|
Author-email: Chris Mutel <cmutel@gmail.com>
|
|
6
6
|
Maintainer-email: Chris Mutel <cmutel@gmail.com>
|
|
@@ -26,9 +26,9 @@ Requires-Python: >=3.9
|
|
|
26
26
|
Description-Content-Type: text/markdown
|
|
27
27
|
License-File: LICENSE
|
|
28
28
|
Requires-Dist: numpy
|
|
29
|
-
Requires-Dist: scipy
|
|
29
|
+
Requires-Dist: scipy>=1.10
|
|
30
30
|
Requires-Dist: pandas
|
|
31
|
-
Requires-Dist: bw_processing
|
|
31
|
+
Requires-Dist: bw_processing>=1.0
|
|
32
32
|
Requires-Dist: stats_arrays
|
|
33
33
|
Provides-Extra: testing
|
|
34
34
|
Requires-Dist: matrix_utils; extra == "testing"
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
"source": [
|
|
10
10
|
"import itertools\n",
|
|
11
11
|
"import numpy as np\n",
|
|
12
|
-
"from scipy import sparse"
|
|
12
|
+
"from scipy import sparse\n",
|
|
13
|
+
"import matrix_utils as mu"
|
|
13
14
|
]
|
|
14
15
|
},
|
|
15
16
|
{
|
|
@@ -60,20 +61,120 @@
|
|
|
60
61
|
},
|
|
61
62
|
{
|
|
62
63
|
"cell_type": "code",
|
|
63
|
-
"execution_count":
|
|
64
|
+
"execution_count": 14,
|
|
64
65
|
"id": "wired-lesbian",
|
|
65
66
|
"metadata": {},
|
|
66
67
|
"outputs": [],
|
|
67
68
|
"source": [
|
|
68
69
|
"def index_with_indexarray(array_from):\n",
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
"
|
|
70
|
+
" array = np.unique(array_from)\n",
|
|
71
|
+
" \n",
|
|
72
|
+
" if array_from.shape == (0,):\n",
|
|
73
|
+
" if empty_ok:\n",
|
|
74
|
+
" max_value = 0\n",
|
|
75
|
+
" else:\n",
|
|
76
|
+
" raise EmptyArray(\"Empty array can't be used to map values\")\n",
|
|
77
|
+
" else:\n",
|
|
78
|
+
" max_value = int(array.max())\n",
|
|
79
|
+
" index_array = np.zeros(max_value + 1) - 1\n",
|
|
80
|
+
" index_array[array] = np.arange(len(array))\n",
|
|
72
81
|
"\n",
|
|
73
|
-
"
|
|
74
|
-
"
|
|
82
|
+
" result = np.zeros_like(array_from) - 1\n",
|
|
83
|
+
" mask = array_from <= max_value\n",
|
|
84
|
+
" result[mask] = index_array[array_from[mask]]"
|
|
85
|
+
]
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"cell_type": "code",
|
|
89
|
+
"execution_count": 42,
|
|
90
|
+
"id": "b24eddaa-76e1-4bcc-8db9-4e648f564f13",
|
|
91
|
+
"metadata": {},
|
|
92
|
+
"outputs": [],
|
|
93
|
+
"source": [
|
|
94
|
+
"def index_with_sparse_matrix(array_from):\n",
|
|
95
|
+
" rows = np.unique(array_from)\n",
|
|
96
|
+
" cols = np.zeros_like(rows)\n",
|
|
97
|
+
" values = np.arange(1, len(rows) + 1)\n",
|
|
98
|
+
" matrix = sparse.coo_matrix((values, (rows, cols)), (rows[-1] + 1, 1)).tocsr()\n",
|
|
75
99
|
"\n",
|
|
76
|
-
" return
|
|
100
|
+
" return (matrix[array_from, 0]).tocoo().data"
|
|
101
|
+
]
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"cell_type": "code",
|
|
105
|
+
"execution_count": 43,
|
|
106
|
+
"id": "b6a818cc-00fb-457f-b91d-14044c028efd",
|
|
107
|
+
"metadata": {},
|
|
108
|
+
"outputs": [
|
|
109
|
+
{
|
|
110
|
+
"data": {
|
|
111
|
+
"text/plain": [
|
|
112
|
+
"array([1, 3, 1, 2, 0])"
|
|
113
|
+
]
|
|
114
|
+
},
|
|
115
|
+
"execution_count": 43,
|
|
116
|
+
"metadata": {},
|
|
117
|
+
"output_type": "execute_result"
|
|
118
|
+
}
|
|
119
|
+
],
|
|
120
|
+
"source": [
|
|
121
|
+
"array_from = np.array([4, 19000, 4, 8, 1])\n",
|
|
122
|
+
"index_with_sparse_matrix(array_from)"
|
|
123
|
+
]
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"cell_type": "code",
|
|
127
|
+
"execution_count": 11,
|
|
128
|
+
"id": "d5486625-8bab-4500-8167-66f5a8f851f3",
|
|
129
|
+
"metadata": {},
|
|
130
|
+
"outputs": [
|
|
131
|
+
{
|
|
132
|
+
"data": {
|
|
133
|
+
"text/plain": [
|
|
134
|
+
"<3488834974658x1 sparse array of type '<class 'numpy.int64'>'\n",
|
|
135
|
+
"\twith 4 stored elements in COOrdinate format>"
|
|
136
|
+
]
|
|
137
|
+
},
|
|
138
|
+
"execution_count": 11,
|
|
139
|
+
"metadata": {},
|
|
140
|
+
"output_type": "execute_result"
|
|
141
|
+
}
|
|
142
|
+
],
|
|
143
|
+
"source": [
|
|
144
|
+
"inpt = np.array([1288834974657, 2288834974657, 3488834974657, 3288834974657])\n",
|
|
145
|
+
"array = np.unique(inpt)\n",
|
|
146
|
+
"max_value = array[-1]\n",
|
|
147
|
+
"max_index = len(array) - 1\n",
|
|
148
|
+
"matrix = sparse.coo_array(\n",
|
|
149
|
+
" (np.arange(1, len(array) + 1), (array, np.zeros_like(array))),\n",
|
|
150
|
+
" (max_value + 1, 1),\n",
|
|
151
|
+
") #.todok()\n",
|
|
152
|
+
"matrix"
|
|
153
|
+
]
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
"cell_type": "code",
|
|
157
|
+
"execution_count": 12,
|
|
158
|
+
"id": "562a1c34-32b8-45fc-bf31-519d9b0a83f0",
|
|
159
|
+
"metadata": {},
|
|
160
|
+
"outputs": [
|
|
161
|
+
{
|
|
162
|
+
"ename": "TypeError",
|
|
163
|
+
"evalue": "'coo_array' object is not subscriptable",
|
|
164
|
+
"output_type": "error",
|
|
165
|
+
"traceback": [
|
|
166
|
+
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
|
|
167
|
+
"\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)",
|
|
168
|
+
"Cell \u001b[0;32mIn[12], line 4\u001b[0m\n\u001b[1;32m 2\u001b[0m result \u001b[38;5;241m=\u001b[39m np\u001b[38;5;241m.\u001b[39mzeros_like(inpt) \u001b[38;5;241m-\u001b[39m \u001b[38;5;241m1\u001b[39m\n\u001b[1;32m 3\u001b[0m mask \u001b[38;5;241m=\u001b[39m inpt \u001b[38;5;241m<\u001b[39m\u001b[38;5;241m=\u001b[39m max_value\n\u001b[0;32m----> 4\u001b[0m (\u001b[43mmatrix\u001b[49m\u001b[43m[\u001b[49m\u001b[43minpt\u001b[49m\u001b[43m[\u001b[49m\u001b[43mmask\u001b[49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mnp\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mzeros_like\u001b[49m\u001b[43m(\u001b[49m\u001b[43minpt\u001b[49m\u001b[43m[\u001b[49m\u001b[43mmask\u001b[49m\u001b[43m]\u001b[49m\u001b[43m)\u001b[49m\u001b[43m]\u001b[49m)\n",
|
|
169
|
+
"\u001b[0;31mTypeError\u001b[0m: 'coo_array' object is not subscriptable"
|
|
170
|
+
]
|
|
171
|
+
}
|
|
172
|
+
],
|
|
173
|
+
"source": [
|
|
174
|
+
"inpt = np.array([1288834974657, 2288834974657, 348883974657])\n",
|
|
175
|
+
"result = np.zeros_like(inpt) - 1\n",
|
|
176
|
+
"mask = inpt <= max_value\n",
|
|
177
|
+
"(matrix[inpt[mask], np.zeros_like(inpt[mask])])"
|
|
77
178
|
]
|
|
78
179
|
},
|
|
79
180
|
{
|
|
@@ -113,7 +214,7 @@
|
|
|
113
214
|
},
|
|
114
215
|
{
|
|
115
216
|
"cell_type": "code",
|
|
116
|
-
"execution_count":
|
|
217
|
+
"execution_count": 2,
|
|
117
218
|
"id": "little-marshall",
|
|
118
219
|
"metadata": {},
|
|
119
220
|
"outputs": [],
|
|
@@ -163,36 +264,43 @@
|
|
|
163
264
|
},
|
|
164
265
|
{
|
|
165
266
|
"cell_type": "code",
|
|
166
|
-
"execution_count":
|
|
167
|
-
"id": "
|
|
267
|
+
"execution_count": 15,
|
|
268
|
+
"id": "84f97b1b-eb9a-498b-bf24-979be3212fd4",
|
|
168
269
|
"metadata": {},
|
|
169
|
-
"outputs": [
|
|
270
|
+
"outputs": [
|
|
271
|
+
{
|
|
272
|
+
"name": "stdout",
|
|
273
|
+
"output_type": "stream",
|
|
274
|
+
"text": [
|
|
275
|
+
"12.5 ms ± 126 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n"
|
|
276
|
+
]
|
|
277
|
+
}
|
|
278
|
+
],
|
|
170
279
|
"source": [
|
|
171
|
-
"
|
|
172
|
-
"arr2 = input_array()"
|
|
280
|
+
"%timeit index_with_indexarray(arr)"
|
|
173
281
|
]
|
|
174
282
|
},
|
|
175
283
|
{
|
|
176
284
|
"cell_type": "code",
|
|
177
|
-
"execution_count":
|
|
178
|
-
"id": "
|
|
285
|
+
"execution_count": 44,
|
|
286
|
+
"id": "7491e454-ce31-4132-90c9-0d37f79e92c8",
|
|
179
287
|
"metadata": {},
|
|
180
288
|
"outputs": [
|
|
181
289
|
{
|
|
182
290
|
"name": "stdout",
|
|
183
291
|
"output_type": "stream",
|
|
184
292
|
"text": [
|
|
185
|
-
"
|
|
293
|
+
"121 µs ± 352 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)\n"
|
|
186
294
|
]
|
|
187
295
|
}
|
|
188
296
|
],
|
|
189
297
|
"source": [
|
|
190
|
-
"%timeit
|
|
298
|
+
"%timeit index_with_sparse_matrix(array_from)"
|
|
191
299
|
]
|
|
192
300
|
},
|
|
193
301
|
{
|
|
194
302
|
"cell_type": "code",
|
|
195
|
-
"execution_count":
|
|
303
|
+
"execution_count": 9,
|
|
196
304
|
"id": "systematic-shopping",
|
|
197
305
|
"metadata": {},
|
|
198
306
|
"outputs": [],
|
|
@@ -290,7 +398,7 @@
|
|
|
290
398
|
],
|
|
291
399
|
"metadata": {
|
|
292
400
|
"kernelspec": {
|
|
293
|
-
"display_name": "Python 3",
|
|
401
|
+
"display_name": "Python 3 (ipykernel)",
|
|
294
402
|
"language": "python",
|
|
295
403
|
"name": "python3"
|
|
296
404
|
},
|
|
@@ -304,7 +412,7 @@
|
|
|
304
412
|
"name": "python",
|
|
305
413
|
"nbconvert_exporter": "python",
|
|
306
414
|
"pygments_lexer": "ipython3",
|
|
307
|
-
"version": "3.
|
|
415
|
+
"version": "3.10.14"
|
|
308
416
|
}
|
|
309
417
|
},
|
|
310
418
|
"nbformat": 4,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import numpy as np
|
|
2
|
+
from scipy import sparse
|
|
2
3
|
|
|
3
4
|
from .errors import EmptyArray
|
|
4
5
|
|
|
@@ -23,28 +24,31 @@ class ArrayMapper:
|
|
|
23
24
|
|
|
24
25
|
""" # NOQA: E501
|
|
25
26
|
|
|
26
|
-
def __init__(self, *, array: np.ndarray, sparse_cutoff:
|
|
27
|
+
def __init__(self, *, array: np.ndarray, sparse_cutoff: int = 50000, empty_ok: bool = False):
|
|
27
28
|
self._check_input_array(array)
|
|
28
29
|
|
|
29
30
|
# Even if already unique, this only adds ~2ms for 100.000 elements
|
|
30
31
|
self.array = np.unique(array)
|
|
32
|
+
self.empty_ok = empty_ok
|
|
31
33
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
# The default code will generate a complete mapping for the (min, max)
|
|
36
|
-
# interval, which can use too much memory in certain cases.
|
|
37
|
-
# self.use_sparse = len(self.keys) / self.keys.max() <= sparse_cutoff:
|
|
38
|
-
|
|
39
|
-
if array.shape == (0,):
|
|
40
|
-
if empty_ok:
|
|
34
|
+
if self.array.shape == (0,):
|
|
35
|
+
if self.empty_ok:
|
|
36
|
+
self.empty_input = True
|
|
41
37
|
self.max_value = 0
|
|
38
|
+
self.max_index = 0
|
|
39
|
+
return
|
|
42
40
|
else:
|
|
43
41
|
raise EmptyArray("Empty array can't be used to map values")
|
|
44
42
|
else:
|
|
45
|
-
self.
|
|
46
|
-
|
|
47
|
-
|
|
43
|
+
self.empty_input = False
|
|
44
|
+
self.max_value = self.array[-1]
|
|
45
|
+
self.max_index = len(self.array) - 1
|
|
46
|
+
|
|
47
|
+
# Zero serves as a missing value, so start at one
|
|
48
|
+
self.matrix = sparse.coo_matrix(
|
|
49
|
+
(np.arange(1, len(self.array) + 1), (self.array, np.zeros_like(self.array))),
|
|
50
|
+
(self.max_value + 1, 1),
|
|
51
|
+
).tocsc()
|
|
48
52
|
|
|
49
53
|
def __len__(self):
|
|
50
54
|
return self.array.shape[0]
|
|
@@ -61,16 +65,25 @@ class ArrayMapper:
|
|
|
61
65
|
if array.shape == (0,):
|
|
62
66
|
# Empty array
|
|
63
67
|
return array.copy()
|
|
68
|
+
elif self.empty_input:
|
|
69
|
+
if self.empty_ok:
|
|
70
|
+
# Return all with missing flag
|
|
71
|
+
return np.zeros_like(array) - 1
|
|
72
|
+
else:
|
|
73
|
+
raise EmptyArray("Can't map with empty input array")
|
|
64
74
|
|
|
65
75
|
result = np.zeros_like(array) - 1
|
|
66
76
|
mask = array <= self.max_value
|
|
67
|
-
|
|
77
|
+
# https://numpy.org/doc/stable/reference/generated/numpy.matrix.A1.html
|
|
78
|
+
result[mask] = (self.matrix[array[mask], np.zeros_like(array[mask])]).A1 - 1
|
|
68
79
|
return result
|
|
69
80
|
|
|
70
81
|
def to_dict(self) -> dict:
|
|
71
82
|
"""Turn the mapping arrays into a Python dict. This is only useful for
|
|
72
83
|
human examination, the normal implementation uses Numpy functions on the
|
|
73
84
|
arrays directly."""
|
|
85
|
+
if self.empty_input:
|
|
86
|
+
return {}
|
|
74
87
|
return {int(x): int(y) for x, y in zip(self.array, self.map_array(self.array))}
|
|
75
88
|
|
|
76
89
|
def reverse_dict(self) -> dict:
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
from itertools import product
|
|
2
2
|
from typing import List, Union
|
|
3
3
|
|
|
4
|
+
from numpy import int32, int64
|
|
4
5
|
from numpy.random import PCG64, Generator
|
|
5
6
|
|
|
6
7
|
# Max signed 32 bit integer, compatible with Windows
|
|
7
8
|
MAX_SIGNED_32BIT_INT = 2147483647
|
|
9
|
+
MAX_SIGNED_64BIT_INT = 9223372036854775807
|
|
8
10
|
|
|
9
11
|
|
|
10
12
|
class Indexer:
|
|
@@ -18,15 +20,21 @@ class RandomIndexer(Generator, Indexer):
|
|
|
18
20
|
|
|
19
21
|
Returns indices for a sample array.
|
|
20
22
|
|
|
23
|
+
Because we are creating Python indices, and Python starts indices with zero, the value
|
|
24
|
+
`max_value` is never reached - the maximum generated index is `max_value - 1`.
|
|
25
|
+
|
|
21
26
|
max_value: Number of columns in the array for which a column index is returned.
|
|
22
27
|
seed: Seed for RNG. Optional."""
|
|
23
28
|
|
|
24
|
-
def __init__(self, seed: Union[int, None] = None):
|
|
29
|
+
def __init__(self, seed: Union[int, None] = None, max_value: int = MAX_SIGNED_64BIT_INT):
|
|
25
30
|
self.seed = seed
|
|
31
|
+
self.max_value = max_value
|
|
26
32
|
self.reset()
|
|
27
33
|
|
|
28
34
|
def __next__(self):
|
|
29
|
-
self.index = self.integers(
|
|
35
|
+
self.index = self.integers(
|
|
36
|
+
0, self.max_value, dtype=int32 if self.max_value == MAX_SIGNED_32BIT_INT else int64
|
|
37
|
+
)
|
|
30
38
|
return self.index
|
|
31
39
|
|
|
32
40
|
def reset(self):
|
|
@@ -137,12 +137,12 @@ class MappedMatrix:
|
|
|
137
137
|
col_indices = safe_concatenate_indices([obj.col_matrix for obj in self.groups], empty_ok)
|
|
138
138
|
|
|
139
139
|
if diagonal:
|
|
140
|
-
x =
|
|
140
|
+
x = 0 if self.row_mapper.empty_input else self.row_mapper.max_index + 1
|
|
141
141
|
dimensions = (x, x)
|
|
142
142
|
else:
|
|
143
143
|
dimensions = (
|
|
144
|
-
|
|
145
|
-
|
|
144
|
+
0 if self.row_mapper.empty_input else self.row_mapper.max_index + 1,
|
|
145
|
+
0 if self.col_mapper.empty_input else self.col_mapper.max_index + 1,
|
|
146
146
|
)
|
|
147
147
|
|
|
148
148
|
self.matrix = sparse.coo_matrix(
|
|
@@ -178,6 +178,9 @@ class MappedMatrix:
|
|
|
178
178
|
self.rebuild_matrix()
|
|
179
179
|
|
|
180
180
|
def rebuild_matrix(self) -> None:
|
|
181
|
+
# In theory, setting this to zero instead of multiplying it would
|
|
182
|
+
# save some nanoseconds, but it led to weird Numpy dtype errors and
|
|
183
|
+
# wasn't worth thinking about too much for very little gain.
|
|
181
184
|
self.matrix.data *= 0
|
|
182
185
|
for group in self.groups:
|
|
183
186
|
row, col, data = group.calculate()
|
|
@@ -211,7 +214,10 @@ class MappedMatrix:
|
|
|
211
214
|
for obj in resources:
|
|
212
215
|
obj.add_indexer(indexer=package.indexer)
|
|
213
216
|
else:
|
|
214
|
-
package.indexer = RandomIndexer(
|
|
217
|
+
package.indexer = RandomIndexer(
|
|
218
|
+
seed=seed_override or package.metadata["seed"],
|
|
219
|
+
max_value=package.get_max_index_value(),
|
|
220
|
+
)
|
|
215
221
|
for obj in resources:
|
|
216
222
|
obj.add_indexer(indexer=package.indexer)
|
|
217
223
|
|
|
@@ -270,7 +276,7 @@ class MappedMatrix:
|
|
|
270
276
|
|
|
271
277
|
array = np.zeros(len(given), dtype=UNCERTAINTY_DTYPE)
|
|
272
278
|
for field in FIELDS:
|
|
273
|
-
array[field] = np.
|
|
279
|
+
array[field] = np.nan
|
|
274
280
|
array["loc"] = given
|
|
275
281
|
array["uncertainty_type"] = uncertainty_type
|
|
276
282
|
return array
|
|
@@ -26,7 +26,7 @@ class SparseMatrixDict(dict):
|
|
|
26
26
|
return SparseMatrixDict(
|
|
27
27
|
{unroll(a, b): c @ d.matrix for a, c in self.items() for b, d in other.items()}
|
|
28
28
|
)
|
|
29
|
-
elif sparse.
|
|
29
|
+
elif sparse.issparse(other):
|
|
30
30
|
return SparseMatrixDict({a: b @ other for a, b in self.items()})
|
|
31
31
|
else:
|
|
32
32
|
raise TypeError(f"Can't understand matrix multiplication for type {type(other)}")
|
|
@@ -180,7 +180,7 @@ class MappedMatrixDict(Mapping):
|
|
|
180
180
|
|
|
181
181
|
Note that the mapped matrix dict must come first, i.e. `MappedMatrixDict @ other`.
|
|
182
182
|
"""
|
|
183
|
-
if sparse.
|
|
183
|
+
if sparse.issparse(other):
|
|
184
184
|
return SparseMatrixDict(
|
|
185
185
|
[(key, value.matrix @ other) for key, value in self.matrices.items()]
|
|
186
186
|
)
|
|
@@ -120,7 +120,9 @@ class ResourceGroup:
|
|
|
120
120
|
"""The source data for the indices array."""
|
|
121
121
|
indices = self.get_resource_by_suffix("indices")
|
|
122
122
|
if self.transpose:
|
|
123
|
-
indices = indices.astype(
|
|
123
|
+
indices = indices.astype(
|
|
124
|
+
[("col", indices.dtype[0]), ("row", indices.dtype[0])], copy=False
|
|
125
|
+
)
|
|
124
126
|
return indices
|
|
125
127
|
|
|
126
128
|
def get_resource_by_suffix(self, suffix: str) -> Any:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: matrix_utils
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6
|
|
4
4
|
Summary: Tools to create matrices from data packages
|
|
5
5
|
Author-email: Chris Mutel <cmutel@gmail.com>
|
|
6
6
|
Maintainer-email: Chris Mutel <cmutel@gmail.com>
|
|
@@ -26,9 +26,9 @@ Requires-Python: >=3.9
|
|
|
26
26
|
Description-Content-Type: text/markdown
|
|
27
27
|
License-File: LICENSE
|
|
28
28
|
Requires-Dist: numpy
|
|
29
|
-
Requires-Dist: scipy
|
|
29
|
+
Requires-Dist: scipy>=1.10
|
|
30
30
|
Requires-Dist: pandas
|
|
31
|
-
Requires-Dist: bw_processing
|
|
31
|
+
Requires-Dist: bw_processing>=1.0
|
|
32
32
|
Requires-Dist: stats_arrays
|
|
33
33
|
Provides-Extra: testing
|
|
34
34
|
Requires-Dist: matrix_utils; extra == "testing"
|
|
@@ -12,9 +12,17 @@ def test_initial_setup():
|
|
|
12
12
|
assert np.allclose(am.map_array(inpt), expected)
|
|
13
13
|
|
|
14
14
|
|
|
15
|
+
def test_with_large_values():
|
|
16
|
+
inpt = np.array([1288834974657, 2288834974657, 3488834974657, 3288834974657])
|
|
17
|
+
am = ArrayMapper(array=inpt)
|
|
18
|
+
given = np.array([1288834974657, 228883474657, 3288834974657, 3488834974657])
|
|
19
|
+
expected = np.array([0, -1, 2, 3])
|
|
20
|
+
assert np.allclose(am.map_array(given), expected)
|
|
21
|
+
|
|
22
|
+
|
|
15
23
|
def test_float_indices_raises_error():
|
|
16
24
|
inpt = np.array([1, 2, 3, 6.0])
|
|
17
|
-
with pytest.raises(
|
|
25
|
+
with pytest.raises(TypeError):
|
|
18
26
|
ArrayMapper(array=inpt)
|
|
19
27
|
|
|
20
28
|
|
|
@@ -69,4 +77,4 @@ def test_empty_array_error():
|
|
|
69
77
|
def test_empty_array_ok():
|
|
70
78
|
am = ArrayMapper(array=np.array([], dtype=int), empty_ok=True)
|
|
71
79
|
assert am.array.shape == (0,)
|
|
72
|
-
assert am.
|
|
80
|
+
assert am.empty_input
|
|
@@ -2,63 +2,75 @@ import bw_processing as bwp
|
|
|
2
2
|
import numpy as np
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
def
|
|
5
|
+
def switch_dtype(dp: bwp.Datapackage, indices_32bit: bool) -> tuple:
|
|
6
|
+
if indices_32bit:
|
|
7
|
+
del dp.metadata["64_bit_indices"]
|
|
8
|
+
return [("row", np.int32), ("col", np.int32)]
|
|
9
|
+
else:
|
|
10
|
+
return bwp.INDICES_DTYPE
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def basic_mm(indices_32bit: bool = False, **kwargs):
|
|
6
14
|
dp = bwp.create_datapackage(**kwargs)
|
|
15
|
+
dtype = switch_dtype(dp, indices_32bit)
|
|
7
16
|
dp.add_persistent_vector(
|
|
8
17
|
matrix="foo",
|
|
9
18
|
name="vector",
|
|
10
|
-
indices_array=np.array([(0, 0), (2, 1), (4, 2), (8, 3)], dtype=
|
|
19
|
+
indices_array=np.array([(0, 0), (2, 1), (4, 2), (8, 3)], dtype=dtype),
|
|
11
20
|
data_array=np.array([1, 2.3, 4, 25]),
|
|
12
21
|
)
|
|
13
22
|
dp.add_persistent_vector(
|
|
14
23
|
matrix="foo",
|
|
15
24
|
name="vector2",
|
|
16
|
-
indices_array=np.array([(10, 10), (12, 9), (14, 8), (18, 7)], dtype=
|
|
25
|
+
indices_array=np.array([(10, 10), (12, 9), (14, 8), (18, 7)], dtype=dtype),
|
|
17
26
|
data_array=np.array([11, 12.3, 14, 125]),
|
|
18
27
|
)
|
|
19
28
|
dp.add_persistent_array(
|
|
20
29
|
matrix="foo",
|
|
21
30
|
name="array",
|
|
22
|
-
indices_array=np.array([(1, 0), (2, 1), (5, 1), (8, 1)], dtype=
|
|
31
|
+
indices_array=np.array([(1, 0), (2, 1), (5, 1), (8, 1)], dtype=dtype),
|
|
23
32
|
data_array=np.array([[1, 2.3, 4, 25]]).T,
|
|
24
33
|
)
|
|
25
34
|
return dp
|
|
26
35
|
|
|
27
36
|
|
|
28
|
-
def overlapping(**kwargs):
|
|
37
|
+
def overlapping(indices_32bit: bool = False, **kwargs):
|
|
29
38
|
dp = bwp.create_datapackage(**kwargs)
|
|
39
|
+
dtype = switch_dtype(dp, indices_32bit)
|
|
30
40
|
dp.add_persistent_vector(
|
|
31
41
|
matrix="foo",
|
|
32
42
|
name="vector",
|
|
33
|
-
indices_array=np.array([(0, 0), (2, 1), (4, 2), (8, 3)], dtype=
|
|
43
|
+
indices_array=np.array([(0, 0), (2, 1), (4, 2), (8, 3)], dtype=dtype),
|
|
34
44
|
data_array=np.array([1, 2.3, 4, 25]),
|
|
35
45
|
)
|
|
36
46
|
dp.add_persistent_vector(
|
|
37
47
|
matrix="foo",
|
|
38
48
|
name="vector2",
|
|
39
|
-
indices_array=np.array([(0, 0), (12, 9), (2, 1), (18, 7)], dtype=
|
|
49
|
+
indices_array=np.array([(0, 0), (12, 9), (2, 1), (18, 7)], dtype=dtype),
|
|
40
50
|
data_array=np.array([11, 12.3, 14, 125]),
|
|
41
51
|
)
|
|
42
52
|
return dp
|
|
43
53
|
|
|
44
54
|
|
|
45
|
-
def aggregation(**kwargs):
|
|
55
|
+
def aggregation(indices_32bit: bool = False, **kwargs):
|
|
46
56
|
dp = bwp.create_datapackage(**kwargs)
|
|
57
|
+
dtype = switch_dtype(dp, indices_32bit)
|
|
47
58
|
dp.add_persistent_vector(
|
|
48
59
|
matrix="foo",
|
|
49
60
|
name="vector",
|
|
50
|
-
indices_array=np.array([(0, 0), (2, 1), (4, 2), (4, 2), (8, 3)], dtype=
|
|
61
|
+
indices_array=np.array([(0, 0), (2, 1), (4, 2), (4, 2), (8, 3)], dtype=dtype),
|
|
51
62
|
data_array=np.array([1, 2.3, 4, 17, 25]),
|
|
52
63
|
)
|
|
53
64
|
return dp
|
|
54
65
|
|
|
55
66
|
|
|
56
|
-
def diagonal(**kwargs):
|
|
67
|
+
def diagonal(indices_32bit: bool = False, **kwargs):
|
|
57
68
|
dp = bwp.create_datapackage(**kwargs)
|
|
69
|
+
dtype = switch_dtype(dp, indices_32bit)
|
|
58
70
|
dp.add_persistent_vector(
|
|
59
71
|
matrix="foo",
|
|
60
72
|
name="vector",
|
|
61
|
-
indices_array=np.array([(0, 1), (1, 1), (2, 0), (3, 1)], dtype=
|
|
73
|
+
indices_array=np.array([(0, 1), (1, 1), (2, 0), (3, 1)], dtype=dtype),
|
|
62
74
|
data_array=np.array([1, 2.3, 4, 25]),
|
|
63
75
|
flip_array=np.array([0, 1, 0, 0], dtype=bool),
|
|
64
76
|
)
|
|
@@ -157,10 +157,10 @@ def create_sensitivity_fixtures():
|
|
|
157
157
|
indices_array = np.array([(12, 10), (12, 11), (12, 11), (12, 12)], dtype=INDICES_DTYPE)
|
|
158
158
|
distributions_array = np.zeros((4,), dtype=UNCERTAINTY_DTYPE)
|
|
159
159
|
distributions_array["uncertainty_type"] = (4, 4, 0, 4)
|
|
160
|
-
distributions_array["scale"] = np.
|
|
161
|
-
distributions_array["shape"] = np.
|
|
162
|
-
distributions_array["minimum"] = (0.5, 1.5, np.
|
|
163
|
-
distributions_array["maximum"] = (1.5, 2.5, np.
|
|
160
|
+
distributions_array["scale"] = np.nan
|
|
161
|
+
distributions_array["shape"] = np.nan
|
|
162
|
+
distributions_array["minimum"] = (0.5, 1.5, np.nan, 2.5)
|
|
163
|
+
distributions_array["maximum"] = (1.5, 2.5, np.nan, 3.5)
|
|
164
164
|
distributions_array["loc"] = (1, 2, 1, 3)
|
|
165
165
|
distributions_array["negative"] = (False, False, True, True)
|
|
166
166
|
dp.add_persistent_vector(
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import numpy as np
|
|
2
2
|
|
|
3
3
|
from matrix_utils import CombinatorialIndexer, Proxy, RandomIndexer, SequentialIndexer
|
|
4
|
+
from matrix_utils.indexers import MAX_SIGNED_32BIT_INT, MAX_SIGNED_64BIT_INT
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
def test_random():
|
|
@@ -12,6 +13,17 @@ def test_random():
|
|
|
12
13
|
assert not np.allclose([next(a) for _ in range(10)], [next(b) for _ in range(10)])
|
|
13
14
|
|
|
14
15
|
|
|
16
|
+
def test_indexing_max_value():
|
|
17
|
+
a = RandomIndexer(42, max_value=10)
|
|
18
|
+
values = [next(a) for _ in range(10000)]
|
|
19
|
+
assert max(values) == 10 - 1
|
|
20
|
+
|
|
21
|
+
a = RandomIndexer(42)
|
|
22
|
+
values = [next(a) for _ in range(10000)]
|
|
23
|
+
assert max(values) < MAX_SIGNED_64BIT_INT
|
|
24
|
+
assert max(values) > MAX_SIGNED_32BIT_INT
|
|
25
|
+
|
|
26
|
+
|
|
15
27
|
def test_random_reset():
|
|
16
28
|
a = RandomIndexer(42)
|
|
17
29
|
given = [next(a) for _ in range(10)]
|
|
@@ -1,13 +1,26 @@
|
|
|
1
1
|
import bw_processing as bwp
|
|
2
2
|
import numpy as np
|
|
3
|
+
import pytest
|
|
3
4
|
from fixtures import aggregation, basic_mm, diagonal, overlapping
|
|
4
5
|
|
|
5
6
|
from matrix_utils import MappedMatrix
|
|
6
7
|
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
@pytest.mark.parametrize("smaller", [True, False])
|
|
10
|
+
def test_basic_resource_group_indices_dtype(smaller):
|
|
11
|
+
dp = basic_mm(indices_32bit=smaller)
|
|
12
|
+
|
|
13
|
+
dtype = np.int32 if smaller else np.int64
|
|
14
|
+
|
|
15
|
+
for name in ("vector", "vector2", "array"):
|
|
16
|
+
assert dp.get_resource(f"{name}.indices")[0]["row"].dtype == dtype
|
|
17
|
+
assert dp.get_resource(f"{name}.indices")[0]["col"].dtype == dtype
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@pytest.mark.parametrize("smaller", [True, False])
|
|
21
|
+
def test_basic_matrix_construction(smaller):
|
|
9
22
|
mm = MappedMatrix(
|
|
10
|
-
packages=[basic_mm()],
|
|
23
|
+
packages=[basic_mm(indices_32bit=smaller)],
|
|
11
24
|
matrix="foo",
|
|
12
25
|
use_arrays=False,
|
|
13
26
|
use_distributions=False,
|
|
@@ -21,9 +34,10 @@ def test_basic_matrix_construction():
|
|
|
21
34
|
assert np.allclose(matrix.data, data)
|
|
22
35
|
|
|
23
36
|
|
|
24
|
-
|
|
37
|
+
@pytest.mark.parametrize("smaller", [True, False])
|
|
38
|
+
def test_matrix_construction_transpose(smaller):
|
|
25
39
|
mm = MappedMatrix(
|
|
26
|
-
packages=[diagonal()],
|
|
40
|
+
packages=[diagonal(indices_32bit=smaller)],
|
|
27
41
|
matrix="foo",
|
|
28
42
|
use_arrays=False,
|
|
29
43
|
use_distributions=False,
|
|
@@ -39,7 +53,7 @@ def test_matrix_construction_transpose():
|
|
|
39
53
|
assert np.allclose(matrix.data, data)
|
|
40
54
|
|
|
41
55
|
mm = MappedMatrix(
|
|
42
|
-
packages=[diagonal()],
|
|
56
|
+
packages=[diagonal(indices_32bit=smaller)],
|
|
43
57
|
matrix="foo",
|
|
44
58
|
use_arrays=False,
|
|
45
59
|
use_distributions=False,
|
|
@@ -47,9 +61,14 @@ def test_matrix_construction_transpose():
|
|
|
47
61
|
assert mm.matrix.shape == (4, 2)
|
|
48
62
|
|
|
49
63
|
|
|
50
|
-
|
|
64
|
+
@pytest.mark.parametrize("smaller", [True, False])
|
|
65
|
+
def test_matrix_construction_overlapping_substitution(smaller):
|
|
51
66
|
mm = MappedMatrix(
|
|
52
|
-
packages=[
|
|
67
|
+
packages=[
|
|
68
|
+
overlapping(
|
|
69
|
+
indices_32bit=smaller, sum_intra_duplicates=True, sum_inter_duplicates=False
|
|
70
|
+
)
|
|
71
|
+
],
|
|
53
72
|
matrix="foo",
|
|
54
73
|
use_arrays=False,
|
|
55
74
|
use_distributions=False,
|
|
@@ -64,9 +83,14 @@ def test_matrix_construction_overlapping_substitution():
|
|
|
64
83
|
assert np.allclose(matrix.data, data)
|
|
65
84
|
|
|
66
85
|
|
|
67
|
-
|
|
86
|
+
@pytest.mark.parametrize("smaller", [True, False])
|
|
87
|
+
def test_matrix_construction_overlapping_sum(smaller):
|
|
68
88
|
mm = MappedMatrix(
|
|
69
|
-
packages=[
|
|
89
|
+
packages=[
|
|
90
|
+
overlapping(
|
|
91
|
+
indices_32bit=smaller, sum_intra_duplicates=False, sum_inter_duplicates=True
|
|
92
|
+
)
|
|
93
|
+
],
|
|
70
94
|
matrix="foo",
|
|
71
95
|
use_arrays=False,
|
|
72
96
|
use_distributions=False,
|
|
@@ -76,16 +100,15 @@ def test_matrix_construction_overlapping_sum():
|
|
|
76
100
|
col = np.array([0, 1, 2, 3, 5, 4])
|
|
77
101
|
data = np.array([12, 16.3, 4, 25, 12.3, 125])
|
|
78
102
|
matrix = mm.matrix.tocoo()
|
|
79
|
-
print(matrix)
|
|
80
|
-
print(matrix.data)
|
|
81
103
|
assert np.allclose(matrix.row, row)
|
|
82
104
|
assert np.allclose(matrix.col, col)
|
|
83
105
|
assert np.allclose(matrix.data, data)
|
|
84
106
|
|
|
85
107
|
|
|
86
|
-
|
|
108
|
+
@pytest.mark.parametrize("smaller", [True, False])
|
|
109
|
+
def test_matrix_construction_internal_aggregation(smaller):
|
|
87
110
|
mm = MappedMatrix(
|
|
88
|
-
packages=[aggregation()],
|
|
111
|
+
packages=[aggregation(indices_32bit=smaller)],
|
|
89
112
|
matrix="foo",
|
|
90
113
|
use_arrays=False,
|
|
91
114
|
use_distributions=False,
|
|
@@ -99,9 +122,10 @@ def test_matrix_construction_internal_aggregation():
|
|
|
99
122
|
assert np.allclose(matrix.data, data)
|
|
100
123
|
|
|
101
124
|
|
|
102
|
-
|
|
125
|
+
@pytest.mark.parametrize("smaller", [True, False])
|
|
126
|
+
def test_matrix_construction_no_internal_aggregation(smaller):
|
|
103
127
|
mm = MappedMatrix(
|
|
104
|
-
packages=[aggregation(sum_intra_duplicates=False)],
|
|
128
|
+
packages=[aggregation(indices_32bit=smaller, sum_intra_duplicates=False)],
|
|
105
129
|
matrix="foo",
|
|
106
130
|
use_arrays=False,
|
|
107
131
|
use_distributions=False,
|
|
@@ -614,18 +614,18 @@ def test_input_uncertainties(sensitivity_dps):
|
|
|
614
614
|
|
|
615
615
|
expected = np.array(
|
|
616
616
|
[
|
|
617
|
-
(99, magic % 100, np.
|
|
618
|
-
(99, magic % 100, np.
|
|
619
|
-
(99, magic % 100, np.
|
|
620
|
-
(98, -8.5, 1.118034, np.
|
|
621
|
-
(98, 9.5, 1.118034, np.
|
|
622
|
-
(4, 1, np.
|
|
623
|
-
(4, 2, np.
|
|
624
|
-
(0, 1, np.
|
|
625
|
-
(4, 3, np.
|
|
626
|
-
(99, 1, np.
|
|
627
|
-
(99, 2, np.
|
|
628
|
-
(99, 3, np.
|
|
617
|
+
(99, magic % 100, np.nan, np.nan, np.nan, np.nan, False),
|
|
618
|
+
(99, magic % 100, np.nan, np.nan, np.nan, np.nan, False),
|
|
619
|
+
(99, magic % 100, np.nan, np.nan, np.nan, np.nan, False),
|
|
620
|
+
(98, -8.5, 1.118034, np.nan, np.nan, np.nan, False),
|
|
621
|
+
(98, 9.5, 1.118034, np.nan, np.nan, np.nan, False),
|
|
622
|
+
(4, 1, np.nan, np.nan, 0.5, 1.5, False),
|
|
623
|
+
(4, 2, np.nan, np.nan, 1.5, 2.5, False),
|
|
624
|
+
(0, 1, np.nan, np.nan, np.nan, np.nan, True),
|
|
625
|
+
(4, 3, np.nan, np.nan, 2.5, 3.5, True),
|
|
626
|
+
(99, 1, np.nan, np.nan, np.nan, np.nan, False),
|
|
627
|
+
(99, 2, np.nan, np.nan, np.nan, np.nan, False),
|
|
628
|
+
(99, 3, np.nan, np.nan, np.nan, np.nan, False),
|
|
629
629
|
],
|
|
630
630
|
dtype=bwp.UNCERTAINTY_DTYPE,
|
|
631
631
|
)
|
|
@@ -647,18 +647,18 @@ def test_input_uncertainties_limit_samples(sensitivity_dps):
|
|
|
647
647
|
|
|
648
648
|
expected = np.array(
|
|
649
649
|
[
|
|
650
|
-
(99, magic % 100, np.
|
|
651
|
-
(99, magic % 100, np.
|
|
652
|
-
(99, magic % 100, np.
|
|
653
|
-
(98, -8, 0.8164966, np.
|
|
654
|
-
(98, 9, 0.8164966, np.
|
|
655
|
-
(4, 1, np.
|
|
656
|
-
(4, 2, np.
|
|
657
|
-
(0, 1, np.
|
|
658
|
-
(4, 3, np.
|
|
659
|
-
(99, 1, np.
|
|
660
|
-
(99, 2, np.
|
|
661
|
-
(99, 3, np.
|
|
650
|
+
(99, magic % 100, np.nan, np.nan, np.nan, np.nan, False),
|
|
651
|
+
(99, magic % 100, np.nan, np.nan, np.nan, np.nan, False),
|
|
652
|
+
(99, magic % 100, np.nan, np.nan, np.nan, np.nan, False),
|
|
653
|
+
(98, -8, 0.8164966, np.nan, np.nan, np.nan, False),
|
|
654
|
+
(98, 9, 0.8164966, np.nan, np.nan, np.nan, False),
|
|
655
|
+
(4, 1, np.nan, np.nan, 0.5, 1.5, False),
|
|
656
|
+
(4, 2, np.nan, np.nan, 1.5, 2.5, False),
|
|
657
|
+
(0, 1, np.nan, np.nan, np.nan, np.nan, True),
|
|
658
|
+
(4, 3, np.nan, np.nan, 2.5, 3.5, True),
|
|
659
|
+
(99, 1, np.nan, np.nan, np.nan, np.nan, False),
|
|
660
|
+
(99, 2, np.nan, np.nan, np.nan, np.nan, False),
|
|
661
|
+
(99, 3, np.nan, np.nan, np.nan, np.nan, False),
|
|
662
662
|
],
|
|
663
663
|
dtype=bwp.UNCERTAINTY_DTYPE,
|
|
664
664
|
)
|
|
@@ -680,18 +680,18 @@ def test_input_uncertainties_no_distributions(sensitivity_dps):
|
|
|
680
680
|
|
|
681
681
|
expected = np.array(
|
|
682
682
|
[
|
|
683
|
-
(99, magic % 100, np.
|
|
684
|
-
(99, magic % 100, np.
|
|
685
|
-
(99, magic % 100, np.
|
|
686
|
-
(98, -8.5, 1.118034, np.
|
|
687
|
-
(98, 9.5, 1.118034, np.
|
|
688
|
-
(0, 1, np.
|
|
689
|
-
(0, 2, np.
|
|
690
|
-
(0, -1, np.
|
|
691
|
-
(0, -3, np.
|
|
692
|
-
(99, 1, np.
|
|
693
|
-
(99, 2, np.
|
|
694
|
-
(99, 3, np.
|
|
683
|
+
(99, magic % 100, np.nan, np.nan, np.nan, np.nan, False),
|
|
684
|
+
(99, magic % 100, np.nan, np.nan, np.nan, np.nan, False),
|
|
685
|
+
(99, magic % 100, np.nan, np.nan, np.nan, np.nan, False),
|
|
686
|
+
(98, -8.5, 1.118034, np.nan, np.nan, np.nan, False),
|
|
687
|
+
(98, 9.5, 1.118034, np.nan, np.nan, np.nan, False),
|
|
688
|
+
(0, 1, np.nan, np.nan, np.nan, np.nan, False),
|
|
689
|
+
(0, 2, np.nan, np.nan, np.nan, np.nan, False),
|
|
690
|
+
(0, -1, np.nan, np.nan, np.nan, np.nan, False),
|
|
691
|
+
(0, -3, np.nan, np.nan, np.nan, np.nan, False),
|
|
692
|
+
(99, 1, np.nan, np.nan, np.nan, np.nan, False),
|
|
693
|
+
(99, 2, np.nan, np.nan, np.nan, np.nan, False),
|
|
694
|
+
(99, 3, np.nan, np.nan, np.nan, np.nan, False),
|
|
695
695
|
],
|
|
696
696
|
dtype=bwp.UNCERTAINTY_DTYPE,
|
|
697
697
|
)
|
|
@@ -736,7 +736,6 @@ def test_input_index_vector(sensitivity_dps):
|
|
|
736
736
|
(942484272, 942484272, 1, 1),
|
|
737
737
|
]
|
|
738
738
|
for row in expected:
|
|
739
|
-
print(mm.input_indexer_vector())
|
|
740
739
|
assert np.allclose(mm.input_indexer_vector(), row)
|
|
741
740
|
try:
|
|
742
741
|
next(mm)
|
|
@@ -44,7 +44,7 @@ def create_dp(vector, array, distributions):
|
|
|
44
44
|
indices_array=np.array([(0, 0)], dtype=bwp.INDICES_DTYPE),
|
|
45
45
|
distributions_array=np.array(
|
|
46
46
|
[
|
|
47
|
-
(4, 0.5, np.
|
|
47
|
+
(4, 0.5, np.nan, np.nan, 0.2, 0.8, False),
|
|
48
48
|
],
|
|
49
49
|
dtype=bwp.UNCERTAINTY_DTYPE,
|
|
50
50
|
),
|
|
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
|
{matrix_utils-0.4.3 → matrix_utils-0.6}/dev/Real-time modification of hybrid databases.ipynb
RENAMED
|
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
|