ga-matrix 0.1.0__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.
@@ -0,0 +1,11 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ ## 0.1.0 - 2026-09-01
6
+
7
+ - Prepared the package for GitHub and PyPI publication as `ga-matrix`.
8
+ - Added README, MIT license, gitignore, package version source, and typed package marker.
9
+ - Corrected packaging metadata, project URLs, coverage source, and GitHub Actions imports.
10
+ - Reworked tests around `pytest` and removed heavyweight performance checks from unit tests.
11
+ - Fixed in-place subtraction and division behavior in matrix operations.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 GA Matrix contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,2 @@
1
+ include CHANGELOG.md
2
+ recursive-include docs *.md
@@ -0,0 +1,206 @@
1
+ Metadata-Version: 2.4
2
+ Name: ga-matrix
3
+ Version: 0.1.0
4
+ Summary: Label-aware origin-destination matrix utilities built on NumPy and pandas.
5
+ Author: GA Matrix contributors
6
+ License-Expression: MIT
7
+ Project-URL: Documentation, https://github.com/andreagemma/matrix#readme
8
+ Project-URL: Issues, https://github.com/andreagemma/matrix/issues
9
+ Project-URL: Source, https://github.com/andreagemma/matrix
10
+ Keywords: ga-matrix,matrix,origin-destination,numpy,pandas
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3 :: Only
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
+ Classifier: Typing :: Typed
20
+ Requires-Python: >=3.10
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Requires-Dist: numpy>=1.24
24
+ Requires-Dist: pandas>=2.0
25
+ Provides-Extra: test
26
+ Requires-Dist: pytest>=8.0; extra == "test"
27
+ Requires-Dist: pytest-cov>=5.0; extra == "test"
28
+ Provides-Extra: dev
29
+ Requires-Dist: build>=1.2; extra == "dev"
30
+ Requires-Dist: mypy>=1.10; extra == "dev"
31
+ Requires-Dist: pytest>=8.0; extra == "dev"
32
+ Requires-Dist: pytest-cov>=5.0; extra == "dev"
33
+ Requires-Dist: ruff>=0.5; extra == "dev"
34
+ Requires-Dist: twine>=5.1; extra == "dev"
35
+ Dynamic: license-file
36
+
37
+ # GA Matrix
38
+
39
+ [![CI](https://github.com/andreagemma/matrix/actions/workflows/ci.yml/badge.svg)](https://github.com/andreagemma/matrix/actions/workflows/ci.yml)
40
+ [![PyPI](https://img.shields.io/pypi/v/ga-matrix.svg)](https://pypi.org/project/ga-matrix/)
41
+ [![Python](https://img.shields.io/pypi/pyversions/ga-matrix.svg)](https://pypi.org/project/ga-matrix/)
42
+
43
+ GA Matrix provides small NumPy-backed matrix containers with label-based access,
44
+ long-form pandas import/export helpers, and optional timestamp support for
45
+ origin-destination data.
46
+
47
+ The PyPI distribution is named `ga-matrix`; the import package is named `matrix`.
48
+
49
+ ## Installation
50
+
51
+ ```bash
52
+ python -m pip install ga-matrix
53
+ ```
54
+
55
+ Development and test tools are available as extras:
56
+
57
+ ```bash
58
+ python -m pip install -e ".[test]"
59
+ python -m pip install -e ".[dev]"
60
+ ```
61
+
62
+ ## Quick Start
63
+
64
+ ```python
65
+ from matrix import MatrixOD
66
+
67
+ rows = ["A", "B"]
68
+ cols = ["X", "Y"]
69
+
70
+ od = MatrixOD(rows, cols, init={"A": {"X": 10}, "B": {"Y": 5}})
71
+ od["A", "Y"] = 3
72
+
73
+ assert od["A", "X"] == 10
74
+ assert od.sum() == 18
75
+ ```
76
+
77
+ ## MatrixOD
78
+
79
+ `MatrixOD` stores a 2D origin-destination matrix. Rows and columns can be passed
80
+ as label sequences or existing label-to-position mappings.
81
+
82
+ ```python
83
+ import pandas as pd
84
+
85
+ from matrix import MatrixOD
86
+
87
+ df = pd.DataFrame(
88
+ [
89
+ {"origin": "A", "destination": "X", "trips": 10},
90
+ {"origin": "B", "destination": "Y", "trips": 5},
91
+ ]
92
+ )
93
+
94
+ od = MatrixOD.read_df(
95
+ rows=["A", "B"],
96
+ cols=["X", "Y"],
97
+ df=df,
98
+ o_field="origin",
99
+ d_field="destination",
100
+ value_field="trips",
101
+ )
102
+
103
+ roundtrip = od.write_df(o_field="origin", d_field="destination", value_field="trips")
104
+ ```
105
+
106
+ Supported operations are element-wise addition, subtraction, multiplication, and
107
+ division with either a scalar or another matrix with the same labels.
108
+
109
+ ```python
110
+ scaled = od * 1.2
111
+ delta = scaled - od
112
+ col_totals = od.sum(axis=0)
113
+ row_totals = od.sum(axis=1)
114
+ ```
115
+
116
+ ## MatrixODT
117
+
118
+ `MatrixODT` stores one `MatrixOD` per timestamp.
119
+
120
+ ```python
121
+ from matrix import MatrixODT
122
+
123
+ odt = MatrixODT(
124
+ rows=["A", "B"],
125
+ cols=["X", "Y"],
126
+ timestamps=[0, 1],
127
+ init={
128
+ 0: {"A": {"X": 10}},
129
+ 1: {"B": {"Y": 5}},
130
+ },
131
+ )
132
+
133
+ assert odt["A", "X", 0] == 10
134
+ assert odt["A", "X", 99] == 0
135
+ assert odt.sum(axis=2)["A", "X"] == 10
136
+ ```
137
+
138
+ `MatrixODT.read_df()` accepts a long-form DataFrame with origin, destination,
139
+ timestamp, and value columns. If `timestamps` is omitted, timestamp labels are
140
+ inferred from the DataFrame in first-seen order.
141
+
142
+ ## LabeledMatrix
143
+
144
+ `LabeledMatrix` is a more generic 2D labeled array with `.loc` and `.iloc`
145
+ indexers:
146
+
147
+ ```python
148
+ from matrix import LabeledMatrix
149
+
150
+ table = LabeledMatrix(
151
+ [[1, 2], [3, 4]],
152
+ row_index=["a", "b"],
153
+ col_index=["x", "y"],
154
+ )
155
+
156
+ assert table.loc["b", "y"] == 4
157
+ ```
158
+
159
+ ## API Summary
160
+
161
+ - `MatrixOD(rows, cols, init=None, copy=False, mode=None)`
162
+ - `MatrixOD.read_df(rows, cols, df, o_field="o", d_field="d", value_field="value")`
163
+ - `MatrixOD.read_csv(rows, cols, file, ...)`
164
+ - `MatrixOD.write_df(...)`
165
+ - `MatrixOD.write_csv(file, ...)`
166
+ - `MatrixODT(rows, cols, timestamps, init=None, copy=False, mode=None)`
167
+ - `MatrixODT.read_df(rows, cols, timestamps=None, df=None, ...)`
168
+ - `MatrixODT.read_csv(rows, cols, file, timestamps=None, ...)`
169
+ - `MatrixODT.write_df(...)`
170
+ - `MatrixODT.write_csv(file, ...)`
171
+ - `LabeledMatrix(data, row_index=..., col_index=..., dtype=None, copy=False)`
172
+
173
+ ## Development
174
+
175
+ GA Matrix supports Python 3.10 and newer.
176
+
177
+ ```bash
178
+ python -m pip install -e ".[dev]"
179
+ python -m compileall -q src
180
+ python -m pytest --cov=matrix --cov-report=term-missing
181
+ ruff check .
182
+ mypy
183
+ python -m pip check
184
+ python -m build
185
+ python -m twine check dist/*
186
+ ```
187
+
188
+ ## Releases
189
+
190
+ `src/matrix/_version.py` is the only version source. To publish a release:
191
+
192
+ 1. Update `__version__` in `_version.py` and commit the release changes.
193
+ 2. Push `main` and wait for CI to pass.
194
+ 3. Configure the PyPI Trusted Publisher with project `ga-matrix`, owner
195
+ `andreagemma`, repository `matrix`, workflow `release.yml`, and environment
196
+ `pypi`.
197
+ 4. Run the **Create release** GitHub Actions workflow. With no override it creates
198
+ the `v<version>` tag, creates release notes, and dispatches the build and PyPI
199
+ publication workflow.
200
+
201
+ PyPI versions are immutable. Increment `_version.py` before publishing different
202
+ content.
203
+
204
+ ## License
205
+
206
+ GA Matrix is distributed under the MIT License. See [LICENSE](LICENSE).
@@ -0,0 +1,170 @@
1
+ # GA Matrix
2
+
3
+ [![CI](https://github.com/andreagemma/matrix/actions/workflows/ci.yml/badge.svg)](https://github.com/andreagemma/matrix/actions/workflows/ci.yml)
4
+ [![PyPI](https://img.shields.io/pypi/v/ga-matrix.svg)](https://pypi.org/project/ga-matrix/)
5
+ [![Python](https://img.shields.io/pypi/pyversions/ga-matrix.svg)](https://pypi.org/project/ga-matrix/)
6
+
7
+ GA Matrix provides small NumPy-backed matrix containers with label-based access,
8
+ long-form pandas import/export helpers, and optional timestamp support for
9
+ origin-destination data.
10
+
11
+ The PyPI distribution is named `ga-matrix`; the import package is named `matrix`.
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ python -m pip install ga-matrix
17
+ ```
18
+
19
+ Development and test tools are available as extras:
20
+
21
+ ```bash
22
+ python -m pip install -e ".[test]"
23
+ python -m pip install -e ".[dev]"
24
+ ```
25
+
26
+ ## Quick Start
27
+
28
+ ```python
29
+ from matrix import MatrixOD
30
+
31
+ rows = ["A", "B"]
32
+ cols = ["X", "Y"]
33
+
34
+ od = MatrixOD(rows, cols, init={"A": {"X": 10}, "B": {"Y": 5}})
35
+ od["A", "Y"] = 3
36
+
37
+ assert od["A", "X"] == 10
38
+ assert od.sum() == 18
39
+ ```
40
+
41
+ ## MatrixOD
42
+
43
+ `MatrixOD` stores a 2D origin-destination matrix. Rows and columns can be passed
44
+ as label sequences or existing label-to-position mappings.
45
+
46
+ ```python
47
+ import pandas as pd
48
+
49
+ from matrix import MatrixOD
50
+
51
+ df = pd.DataFrame(
52
+ [
53
+ {"origin": "A", "destination": "X", "trips": 10},
54
+ {"origin": "B", "destination": "Y", "trips": 5},
55
+ ]
56
+ )
57
+
58
+ od = MatrixOD.read_df(
59
+ rows=["A", "B"],
60
+ cols=["X", "Y"],
61
+ df=df,
62
+ o_field="origin",
63
+ d_field="destination",
64
+ value_field="trips",
65
+ )
66
+
67
+ roundtrip = od.write_df(o_field="origin", d_field="destination", value_field="trips")
68
+ ```
69
+
70
+ Supported operations are element-wise addition, subtraction, multiplication, and
71
+ division with either a scalar or another matrix with the same labels.
72
+
73
+ ```python
74
+ scaled = od * 1.2
75
+ delta = scaled - od
76
+ col_totals = od.sum(axis=0)
77
+ row_totals = od.sum(axis=1)
78
+ ```
79
+
80
+ ## MatrixODT
81
+
82
+ `MatrixODT` stores one `MatrixOD` per timestamp.
83
+
84
+ ```python
85
+ from matrix import MatrixODT
86
+
87
+ odt = MatrixODT(
88
+ rows=["A", "B"],
89
+ cols=["X", "Y"],
90
+ timestamps=[0, 1],
91
+ init={
92
+ 0: {"A": {"X": 10}},
93
+ 1: {"B": {"Y": 5}},
94
+ },
95
+ )
96
+
97
+ assert odt["A", "X", 0] == 10
98
+ assert odt["A", "X", 99] == 0
99
+ assert odt.sum(axis=2)["A", "X"] == 10
100
+ ```
101
+
102
+ `MatrixODT.read_df()` accepts a long-form DataFrame with origin, destination,
103
+ timestamp, and value columns. If `timestamps` is omitted, timestamp labels are
104
+ inferred from the DataFrame in first-seen order.
105
+
106
+ ## LabeledMatrix
107
+
108
+ `LabeledMatrix` is a more generic 2D labeled array with `.loc` and `.iloc`
109
+ indexers:
110
+
111
+ ```python
112
+ from matrix import LabeledMatrix
113
+
114
+ table = LabeledMatrix(
115
+ [[1, 2], [3, 4]],
116
+ row_index=["a", "b"],
117
+ col_index=["x", "y"],
118
+ )
119
+
120
+ assert table.loc["b", "y"] == 4
121
+ ```
122
+
123
+ ## API Summary
124
+
125
+ - `MatrixOD(rows, cols, init=None, copy=False, mode=None)`
126
+ - `MatrixOD.read_df(rows, cols, df, o_field="o", d_field="d", value_field="value")`
127
+ - `MatrixOD.read_csv(rows, cols, file, ...)`
128
+ - `MatrixOD.write_df(...)`
129
+ - `MatrixOD.write_csv(file, ...)`
130
+ - `MatrixODT(rows, cols, timestamps, init=None, copy=False, mode=None)`
131
+ - `MatrixODT.read_df(rows, cols, timestamps=None, df=None, ...)`
132
+ - `MatrixODT.read_csv(rows, cols, file, timestamps=None, ...)`
133
+ - `MatrixODT.write_df(...)`
134
+ - `MatrixODT.write_csv(file, ...)`
135
+ - `LabeledMatrix(data, row_index=..., col_index=..., dtype=None, copy=False)`
136
+
137
+ ## Development
138
+
139
+ GA Matrix supports Python 3.10 and newer.
140
+
141
+ ```bash
142
+ python -m pip install -e ".[dev]"
143
+ python -m compileall -q src
144
+ python -m pytest --cov=matrix --cov-report=term-missing
145
+ ruff check .
146
+ mypy
147
+ python -m pip check
148
+ python -m build
149
+ python -m twine check dist/*
150
+ ```
151
+
152
+ ## Releases
153
+
154
+ `src/matrix/_version.py` is the only version source. To publish a release:
155
+
156
+ 1. Update `__version__` in `_version.py` and commit the release changes.
157
+ 2. Push `main` and wait for CI to pass.
158
+ 3. Configure the PyPI Trusted Publisher with project `ga-matrix`, owner
159
+ `andreagemma`, repository `matrix`, workflow `release.yml`, and environment
160
+ `pypi`.
161
+ 4. Run the **Create release** GitHub Actions workflow. With no override it creates
162
+ the `v<version>` tag, creates release notes, and dispatches the build and PyPI
163
+ publication workflow.
164
+
165
+ PyPI versions are immutable. Increment `_version.py` before publishing different
166
+ content.
167
+
168
+ ## License
169
+
170
+ GA Matrix is distributed under the MIT License. See [LICENSE](LICENSE).
@@ -0,0 +1,66 @@
1
+ # API Reference
2
+
3
+ ## `MatrixOD`
4
+
5
+ ```python
6
+ MatrixOD(rows, cols, init=None, copy=False, mode=None)
7
+ ```
8
+
9
+ Creates a NumPy-backed matrix addressed by row and column labels.
10
+
11
+ Main methods:
12
+
13
+ - `copy(copy_data=True)`
14
+ - `transpose()`
15
+ - `inverse()`
16
+ - `get_diagonal()`
17
+ - `set_diagonal(values)`
18
+ - `nan_to_num(copy=True, nan=0.0, posinf=None, neginf=None)`
19
+ - `sum(axis=None)`
20
+ - `read_df(rows, cols, df, o_field="o", d_field="d", value_field="value")`
21
+ - `read_csv(rows, cols, file, ...)`
22
+ - `write_df(...)`
23
+ - `write_csv(file, ...)`
24
+
25
+ Arithmetic with scalars or label-aligned `MatrixOD` instances is element-wise.
26
+
27
+ ## `MatrixODT`
28
+
29
+ ```python
30
+ MatrixODT(rows, cols, timestamps, init=None, copy=False, mode=None)
31
+ ```
32
+
33
+ Creates a timestamp-indexed collection of `MatrixOD` objects. Scalar access uses
34
+ `matrix[origin, destination, timestamp]`; timestamp access uses `matrix[timestamp]`.
35
+
36
+ Main methods:
37
+
38
+ - `copy(copy_data=True)`
39
+ - `sum(axis=None)`
40
+ - `nan_to_num(copy=True, nan=0.0, posinf=None, neginf=None)`
41
+ - `read_df(rows, cols, timestamps=None, df=None, ...)`
42
+ - `read_csv(rows, cols, file, timestamps=None, ...)`
43
+ - `write_df(...)`
44
+ - `write_csv(file, ...)`
45
+
46
+ Arithmetic with scalars or label-aligned `MatrixODT` instances is element-wise.
47
+ When two `MatrixODT` objects contain different timestamps, missing timestamps are
48
+ treated as zero matrices.
49
+
50
+ ## `LabeledMatrix`
51
+
52
+ ```python
53
+ LabeledMatrix(data, row_index=..., col_index=..., dtype=None, copy=False)
54
+ ```
55
+
56
+ Creates a generic labeled 2D NumPy array. Use direct indexing for scalar access,
57
+ `.loc` for label-based indexing, and `.iloc` for position-based indexing.
58
+
59
+ Main methods:
60
+
61
+ - `from_dict_of_dicts(data, dtype=None, row_order=None, col_order=None, fill_value=0)`
62
+ - `reindex(rows=None, cols=None, fill_value=0)`
63
+ - `rename(rows=None, cols=None)`
64
+ - `tolist()`
65
+ - `to_numpy(copy=False)`
66
+ - `to_pandas()`
@@ -0,0 +1,8 @@
1
+ # GA Matrix Documentation
2
+
3
+ GA Matrix contains lightweight matrix containers for label-based origin-destination
4
+ data.
5
+
6
+ - See [API Reference](api.md) for the public classes and methods.
7
+ - See the project [README](../README.md) for installation, quick start, and release
8
+ instructions.
@@ -0,0 +1,86 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "ga-matrix"
7
+ dynamic = ["version"]
8
+ description = "Label-aware origin-destination matrix utilities built on NumPy and pandas."
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = "MIT"
12
+ license-files = ["LICENSE"]
13
+ authors = [
14
+ { name = "GA Matrix contributors" }
15
+ ]
16
+ keywords = ["ga-matrix", "matrix", "origin-destination", "numpy", "pandas"]
17
+ classifiers = [
18
+ "Development Status :: 3 - Alpha",
19
+ "Intended Audience :: Developers",
20
+ "Programming Language :: Python :: 3 :: Only",
21
+ "Programming Language :: Python :: 3.10",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ "Programming Language :: Python :: 3.13",
25
+ "Programming Language :: Python :: 3.14",
26
+ "Typing :: Typed"
27
+ ]
28
+ dependencies = [
29
+ "numpy>=1.24",
30
+ "pandas>=2.0"
31
+ ]
32
+
33
+ [project.optional-dependencies]
34
+ test = [
35
+ "pytest>=8.0",
36
+ "pytest-cov>=5.0"
37
+ ]
38
+ dev = [
39
+ "build>=1.2",
40
+ "mypy>=1.10",
41
+ "pytest>=8.0",
42
+ "pytest-cov>=5.0",
43
+ "ruff>=0.5",
44
+ "twine>=5.1"
45
+ ]
46
+
47
+ [project.urls]
48
+ Documentation = "https://github.com/andreagemma/matrix#readme"
49
+ Issues = "https://github.com/andreagemma/matrix/issues"
50
+ Source = "https://github.com/andreagemma/matrix"
51
+
52
+ [tool.setuptools]
53
+ package-dir = {"" = "src"}
54
+
55
+ [tool.setuptools.packages.find]
56
+ where = ["src"]
57
+
58
+ [tool.setuptools.package-data]
59
+ matrix = ["py.typed"]
60
+
61
+ [tool.setuptools.dynamic]
62
+ version = {attr = "matrix._version.__version__"}
63
+
64
+ [tool.pytest.ini_options]
65
+ testpaths = ["tests"]
66
+ addopts = "-ra --strict-markers"
67
+
68
+ [tool.coverage.run]
69
+ branch = true
70
+ source = ["matrix"]
71
+
72
+ [tool.ruff]
73
+ line-length = 100
74
+ target-version = "py310"
75
+
76
+ [tool.ruff.lint]
77
+ select = ["E", "F", "I", "UP", "B", "SIM"]
78
+
79
+ [tool.mypy]
80
+ python_version = "3.10"
81
+ files = ["src"]
82
+ warn_unused_configs = true
83
+ check_untyped_defs = true
84
+ follow_imports = "skip"
85
+ no_site_packages = true
86
+ ignore_missing_imports = true
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+