[![tests](https://github.com/alugowski/matrepr/actions/workflows/tests.yml/badge.svg)](https://github.com/alugowski/matrepr/actions/workflows/tests.yml)
[![codecov](https://codecov.io/gh/alugowski/matrepr/graph/badge.svg?token=e9QEAd57gz)](https://codecov.io/gh/alugowski/matrepr)
[![PyPI version](https://badge.fury.io/py/matrepr.svg)](https://pypi.org/project/matrepr/)
[![Conda Version](https://img.shields.io/conda/vn/conda-forge/matrepr.svg)](https://anaconda.org/conda-forge/matrepr)
# MatRepr
Make every matrix beautiful.
MatRepr formats matrices and tensors to HTML, string, and LaTeX, with Jupyter integration.
See [Jupyter notebook for examples.](https://nbviewer.org/github/alugowski/matrepr/blob/main/doc/demo.ipynb)
Brief examples:
```python
from matrepr import mdisplay, mprint
```
`mprint(A)` or `to_str(A)`:
```
<1000×1000, 212345 'float64' elements, coo>
0 1 2 3 4 5 6 7
┌ ┐
0 │ 0.3876 ... │
1 │ 0.5801 0.5085 0.8927 0.629 ... │
2 │ ... │
3 │ 0.7142 ... │
4 │ 0.8631 ... │
5 │ 0.7863 0.1298 0.9918 0.71 0.3444 ... │
6 │ 0.9481 0.9609 ... │
7 │ 0.09361 0.1679 ... │
8 │ 0.4023 ... │
│ : : : : : : : : ... │
└ ┘
```
`mdisplay(A)` or `to_html(A)`:
<img src="https://raw.githubusercontent.com/alugowski/matrepr/main/doc/images/html.png" width=400 alt="HTML screenshot"/><br>
Supports:
* **SciPy** - sparse matrices and arrays like `csr_matrix` and `coo_array`
* **NumPy** - `ndarray` [(demo)](https://nbviewer.org/github/alugowski/matrepr/blob/main/doc/demo-numpy.ipynb)
* **[PyTorch](https://pytorch.org/docs/stable/sparse.html)** - dense and sparse `torch.Tensor` [(demo)](https://nbviewer.org/github/alugowski/matrepr/blob/main/doc/demo-pytorch.ipynb)
* **[TensorFlow](https://www.tensorflow.org/guide/sparse_tensor)** - `tf.Tensor` and `tf.SparseTensor` [(demo)](https://nbviewer.org/github/alugowski/matrepr/blob/main/doc/demo-tensorflow.ipynb)
* **[Python-graphblas](https://github.com/python-graphblas/python-graphblas)** - `gb.Matrix` and `gb.Vector` [(demo)](https://nbviewer.org/github/alugowski/matrepr/blob/main/doc/demo-python-graphblas.ipynb)
* **[PyData/Sparse](https://sparse.pydata.org/)** - `COO`, `DOK`, `GCXS` [(demo)](https://nbviewer.org/github/alugowski/matrepr/blob/main/doc/demo-pydata-sparse.ipynb)
* `list`, `tuple`, including multi-dimensional and ragged
Features:
* Jupyter extension to format matrices in cell outputs.
* Configurable float precision or format string.
* Toggle row and column indices or set your own labels.
* Nested sub-matrices of any supported type, including mixing packages.
* Toggle matrix description or set your own title.
* String output can optionally autodetect terminal width.
* Methods to directly display a matrix (`mprint`, `mdisplay` for Jupyter)
* Methods to convert to string (`to_html`, `to_latex`, `to_str`).
* Configurable per method call or set defaults with `matrepr.params`.
* A `__repr__` monkey patch to format matrices in the Python shell.
* Fast.
Install:
```shell
pip install matrepr
```
or
```shell
conda install matrepr
```
## More Examples
### HTML
<img src="https://raw.githubusercontent.com/alugowski/matrepr/main/doc/images/html-cities.png" width=400 alt="HTML screenshot"/><br>
<img src="https://raw.githubusercontent.com/alugowski/matrepr/main/doc/images/html-4d.png" width=400 alt="4D NumPy Array"/><br>
<img src="https://raw.githubusercontent.com/alugowski/matrepr/main/doc/images/html-adjacency.png" width=290 alt="Adjacency Matrix"/><br>
`mdisplay(A)`, `to_html(A)`
or simply `A` with Jupyter extension `%load_ext matrepr`
### LaTeX
<img src="https://raw.githubusercontent.com/alugowski/matrepr/main/doc/images/latex.png" width=400 alt="LaTeX screenshot"/><br>
<img src="https://raw.githubusercontent.com/alugowski/matrepr/main/doc/images/latex-edgecases.png" width=600 alt="LaTeX edgecases screenshot"/>
`mdisplay(A, 'latex')`, `to_latex(A)`
or simply `A` with Jupyter extension `%load_ext matrepr.latex`
## Jupyter Extension
MatRepr's Jupyter extension registers with [Jupyter's formatter](https://ipython.readthedocs.io/en/stable/config/integrating.html)
to format supported matrices with MatRepr. Simply:
```jupyter
%load_ext matrepr
```
Or if you prefer LaTeX:
```jupyter
%load_ext matrepr.latex
```
Example:
<img src="https://raw.githubusercontent.com/alugowski/matrepr/main/doc/images/jupyter_register.png" width=600 alt="Jupyter extension screenshot"/>
## Methods
* `to_str(A)`: Format `A` as a text string.
* `to_html(A)`: Format `A` as a plain or notebook-styled HTML table. Returns a string.
* `to_latex(A)`: Format `A` as a LaTeX matrix. Returns a string.
* `mprint(A)`: print `A` as a string to stdout.
* `mdisplay(A)`: Displays the output of `to_html`, `to_latex`, or `to_str` in Jupyter.
**Note:** For Spy plots see [MatSpy](https://github.com/alugowski/matspy).
### Arguments
All methods take the same arguments. Apart from the matrix itself:
* `title`: string label. If `True`, then a matrix description is auto generated that contains matrix shape, number and type of nonzeros, etc.
* `indices`: Whether to show matrix indices.
* `max_rows`, `max_rows`: size of table. Matrices larger than this are truncated with ellipses.
* `precision`: floating-point precision
* `num_after_dots`: How many rows/columns to show from the end of the matrix if the entire matrix does not fit.
* `fill_value`: Value to fill empty cells.
#### Overriding defaults
`matrepr.params` contains the default values for all arguments.
For example, to always disable the title, disable indices, and only show the top-left part of the matrix:
```python
matrepr.params.title = False
matrepr.params.indices = False
matrepr.params.num_after_dots = 0
```
## Interactive Python: Monkey Patching `__repr__`
The interactive Python REPL does not have a nice way to register a formatter.
We can monkey patch a `__repl__` method into supported matrix classes for a similar effect.
This is implemented in the [matrepr.patch](matrepr/patch) module. Simply import the patch you want:
* `import matrepr.patch.scipy`
* `import matrepr.patch.graphblas`
* `import matrepr.patch.sparse`
Example:
```
>>> a = scipy.sparse.random(4, 4, density=0.5)
>>> a
<4x4 sparse matrix of type '<class 'numpy.float64'>'
with 8 stored elements in COOrdinate format>
>>> import matrepr.patch.scipy
>>> a
<4×4, 8 'float64' elements, coo>
0 1 2 3
┌ ┐
0 │ 0.6536 0.008388 0.6564 │
1 │ │
2 │ 0.2987 0.8098 │
3 │ 0.1064 0.9613 0.7477 │
└ ┘
```
## Edge Cases
MatRepr gracefully handles:
* multiple elements with the same coordinates (i.e. duplicates)
* nested matrices
* complex values
* string values (including multiline)
* LaTeX scientific notation as $`\times 10^{power}`$
See [demo-edgecases notebook](https://nbviewer.org/github/alugowski/matrepr/blob/main/doc/demo-edgecases.ipynb) for more.
## How does it work?
Each package that MatRepr supports implements two classes:
* `Driver`: Declares what types are supported and supplies an adapter.
* `get_supported_types`: This declares what types are supported, as strings to avoid unnecessary imports.
* `adapt(A)`: Returns a `MatrixAdapter` for a matrix that this driver supports.
* Implement any of these `MatrixAdapter` classes:
* `MatrixAdapterRow`: for structs able to efficiently read a selected row.
* `MatrixAdapterCol`: for structs able to efficiently read a selected column.
* `MatrixAdapterCoo`: for structs able to extract a portion of the matrix as tuples.
See [matrepr.adapters](matrepr/adapters) module for details.
You may use `matspy.register_driver` to register a Driver for your own matrix class.
Raw data
{
"_id": null,
"home_page": null,
"name": "matrepr",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": null,
"keywords": "matrix, tensor, sparse, html, latex, representation, table, numpy, scipy, pydata, graphblas, torch, pytorch, tensorflow",
"author": "Adam Lugowski",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/24/c6/b0efa559db4768544f6b2b2306b7da17f06ebf031f325ca5cbdc7984accc/matrepr-1.0.1.tar.gz",
"platform": null,
"description": "[![tests](https://github.com/alugowski/matrepr/actions/workflows/tests.yml/badge.svg)](https://github.com/alugowski/matrepr/actions/workflows/tests.yml)\n[![codecov](https://codecov.io/gh/alugowski/matrepr/graph/badge.svg?token=e9QEAd57gz)](https://codecov.io/gh/alugowski/matrepr)\n[![PyPI version](https://badge.fury.io/py/matrepr.svg)](https://pypi.org/project/matrepr/)\n[![Conda Version](https://img.shields.io/conda/vn/conda-forge/matrepr.svg)](https://anaconda.org/conda-forge/matrepr)\n\n# MatRepr\n\nMake every matrix beautiful.\n\nMatRepr formats matrices and tensors to HTML, string, and LaTeX, with Jupyter integration.\nSee [Jupyter notebook for examples.](https://nbviewer.org/github/alugowski/matrepr/blob/main/doc/demo.ipynb)\n\nBrief examples:\n\n```python\nfrom matrepr import mdisplay, mprint\n```\n\n`mprint(A)` or `to_str(A)`:\n```\n<1000\u00d71000, 212345 'float64' elements, coo>\n 0 1 2 3 4 5 6 7\n \u250c \u2510\n0 \u2502 0.3876 ... \u2502\n1 \u2502 0.5801 0.5085 0.8927 0.629 ... \u2502\n2 \u2502 ... \u2502\n3 \u2502 0.7142 ... \u2502\n4 \u2502 0.8631 ... \u2502\n5 \u2502 0.7863 0.1298 0.9918 0.71 0.3444 ... \u2502\n6 \u2502 0.9481 0.9609 ... \u2502\n7 \u2502 0.09361 0.1679 ... \u2502\n8 \u2502 0.4023 ... \u2502\n \u2502 : : : : : : : : ... \u2502\n \u2514 \u2518\n```\n\n`mdisplay(A)` or `to_html(A)`:\n\n<img src=\"https://raw.githubusercontent.com/alugowski/matrepr/main/doc/images/html.png\" width=400 alt=\"HTML screenshot\"/><br>\n\nSupports:\n* **SciPy** - sparse matrices and arrays like `csr_matrix` and `coo_array`\n* **NumPy** - `ndarray` [(demo)](https://nbviewer.org/github/alugowski/matrepr/blob/main/doc/demo-numpy.ipynb)\n* **[PyTorch](https://pytorch.org/docs/stable/sparse.html)** - dense and sparse `torch.Tensor` [(demo)](https://nbviewer.org/github/alugowski/matrepr/blob/main/doc/demo-pytorch.ipynb)\n* **[TensorFlow](https://www.tensorflow.org/guide/sparse_tensor)** - `tf.Tensor` and `tf.SparseTensor` [(demo)](https://nbviewer.org/github/alugowski/matrepr/blob/main/doc/demo-tensorflow.ipynb)\n* **[Python-graphblas](https://github.com/python-graphblas/python-graphblas)** - `gb.Matrix` and `gb.Vector` [(demo)](https://nbviewer.org/github/alugowski/matrepr/blob/main/doc/demo-python-graphblas.ipynb)\n* **[PyData/Sparse](https://sparse.pydata.org/)** - `COO`, `DOK`, `GCXS` [(demo)](https://nbviewer.org/github/alugowski/matrepr/blob/main/doc/demo-pydata-sparse.ipynb)\n* `list`, `tuple`, including multi-dimensional and ragged\n\nFeatures:\n* Jupyter extension to format matrices in cell outputs.\n* Configurable float precision or format string.\n* Toggle row and column indices or set your own labels.\n* Nested sub-matrices of any supported type, including mixing packages.\n* Toggle matrix description or set your own title.\n* String output can optionally autodetect terminal width.\n* Methods to directly display a matrix (`mprint`, `mdisplay` for Jupyter)\n* Methods to convert to string (`to_html`, `to_latex`, `to_str`).\n* Configurable per method call or set defaults with `matrepr.params`.\n* A `__repr__` monkey patch to format matrices in the Python shell.\n* Fast.\n\nInstall:\n```shell\npip install matrepr\n```\n\nor\n\n```shell\nconda install matrepr\n```\n\n## More Examples\n\n### HTML\n\n<img src=\"https://raw.githubusercontent.com/alugowski/matrepr/main/doc/images/html-cities.png\" width=400 alt=\"HTML screenshot\"/><br>\n<img src=\"https://raw.githubusercontent.com/alugowski/matrepr/main/doc/images/html-4d.png\" width=400 alt=\"4D NumPy Array\"/><br>\n<img src=\"https://raw.githubusercontent.com/alugowski/matrepr/main/doc/images/html-adjacency.png\" width=290 alt=\"Adjacency Matrix\"/><br> \n\n`mdisplay(A)`, `to_html(A)` \nor simply `A` with Jupyter extension `%load_ext matrepr`\n\n\n### LaTeX\n<img src=\"https://raw.githubusercontent.com/alugowski/matrepr/main/doc/images/latex.png\" width=400 alt=\"LaTeX screenshot\"/><br>\n<img src=\"https://raw.githubusercontent.com/alugowski/matrepr/main/doc/images/latex-edgecases.png\" width=600 alt=\"LaTeX edgecases screenshot\"/>\n\n`mdisplay(A, 'latex')`, `to_latex(A)` \nor simply `A` with Jupyter extension `%load_ext matrepr.latex`\n\n## Jupyter Extension\n\nMatRepr's Jupyter extension registers with [Jupyter's formatter](https://ipython.readthedocs.io/en/stable/config/integrating.html)\nto format supported matrices with MatRepr. Simply:\n\n```jupyter\n%load_ext matrepr\n```\n\nOr if you prefer LaTeX:\n```jupyter\n%load_ext matrepr.latex\n```\n\nExample:\n\n<img src=\"https://raw.githubusercontent.com/alugowski/matrepr/main/doc/images/jupyter_register.png\" width=600 alt=\"Jupyter extension screenshot\"/>\n\n\n## Methods\n* `to_str(A)`: Format `A` as a text string.\n* `to_html(A)`: Format `A` as a plain or notebook-styled HTML table. Returns a string.\n* `to_latex(A)`: Format `A` as a LaTeX matrix. Returns a string.\n* `mprint(A)`: print `A` as a string to stdout.\n* `mdisplay(A)`: Displays the output of `to_html`, `to_latex`, or `to_str` in Jupyter.\n\n**Note:** For Spy plots see [MatSpy](https://github.com/alugowski/matspy).\n\n### Arguments\n\nAll methods take the same arguments. Apart from the matrix itself:\n\n* `title`: string label. If `True`, then a matrix description is auto generated that contains matrix shape, number and type of nonzeros, etc.\n* `indices`: Whether to show matrix indices.\n* `max_rows`, `max_rows`: size of table. Matrices larger than this are truncated with ellipses.\n* `precision`: floating-point precision\n* `num_after_dots`: How many rows/columns to show from the end of the matrix if the entire matrix does not fit.\n* `fill_value`: Value to fill empty cells.\n\n#### Overriding defaults\n`matrepr.params` contains the default values for all arguments.\n\nFor example, to always disable the title, disable indices, and only show the top-left part of the matrix:\n\n```python\nmatrepr.params.title = False\nmatrepr.params.indices = False\nmatrepr.params.num_after_dots = 0\n```\n\n## Interactive Python: Monkey Patching `__repr__`\n\nThe interactive Python REPL does not have a nice way to register a formatter.\n\nWe can monkey patch a `__repl__` method into supported matrix classes for a similar effect.\n\nThis is implemented in the [matrepr.patch](matrepr/patch) module. Simply import the patch you want:\n\n* `import matrepr.patch.scipy`\n* `import matrepr.patch.graphblas`\n* `import matrepr.patch.sparse`\n\nExample:\n\n```\n>>> a = scipy.sparse.random(4, 4, density=0.5)\n>>> a\n<4x4 sparse matrix of type '<class 'numpy.float64'>'\n\twith 8 stored elements in COOrdinate format>\n>>> import matrepr.patch.scipy\n>>> a\n<4\u00d74, 8 'float64' elements, coo>\n 0 1 2 3\n \u250c \u2510\n0 \u2502 0.6536 0.008388 0.6564 \u2502\n1 \u2502 \u2502\n2 \u2502 0.2987 0.8098 \u2502\n3 \u2502 0.1064 0.9613 0.7477 \u2502\n \u2514 \u2518\n```\n\n## Edge Cases\n\nMatRepr gracefully handles:\n * multiple elements with the same coordinates (i.e. duplicates)\n * nested matrices\n * complex values\n * string values (including multiline)\n * LaTeX scientific notation as $`\\times 10^{power}`$\n\nSee [demo-edgecases notebook](https://nbviewer.org/github/alugowski/matrepr/blob/main/doc/demo-edgecases.ipynb) for more.\n\n## How does it work?\n\nEach package that MatRepr supports implements two classes:\n\n* `Driver`: Declares what types are supported and supplies an adapter.\n * `get_supported_types`: This declares what types are supported, as strings to avoid unnecessary imports.\n * `adapt(A)`: Returns a `MatrixAdapter` for a matrix that this driver supports.\n* Implement any of these `MatrixAdapter` classes:\n * `MatrixAdapterRow`: for structs able to efficiently read a selected row.\n * `MatrixAdapterCol`: for structs able to efficiently read a selected column.\n * `MatrixAdapterCoo`: for structs able to extract a portion of the matrix as tuples.\n\nSee [matrepr.adapters](matrepr/adapters) module for details.\n\nYou may use `matspy.register_driver` to register a Driver for your own matrix class.\n",
"bugtrack_url": null,
"license": null,
"summary": "Format matrices and tensors to HTML, string, and LaTeX, with Jupyter integration.",
"version": "1.0.1",
"project_urls": {
"homepage": "https://github.com/alugowski/matrepr",
"repository": "https://github.com/alugowski/matrepr"
},
"split_keywords": [
"matrix",
" tensor",
" sparse",
" html",
" latex",
" representation",
" table",
" numpy",
" scipy",
" pydata",
" graphblas",
" torch",
" pytorch",
" tensorflow"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "26bbb102182970f9bf8d78c32a2e32562e7f80ee4541365cb2630c79fbe8c3b0",
"md5": "f21fdcaaad909eff87b833307eb6af35",
"sha256": "a7a3fac5a8f2fa77b0de73fa4240faef11f381bab1174f9c057f6fec06662bd8"
},
"downloads": -1,
"filename": "matrepr-1.0.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "f21fdcaaad909eff87b833307eb6af35",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7",
"size": 40701,
"upload_time": "2024-07-01T05:37:00",
"upload_time_iso_8601": "2024-07-01T05:37:00.555016Z",
"url": "https://files.pythonhosted.org/packages/26/bb/b102182970f9bf8d78c32a2e32562e7f80ee4541365cb2630c79fbe8c3b0/matrepr-1.0.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "24c6b0efa559db4768544f6b2b2306b7da17f06ebf031f325ca5cbdc7984accc",
"md5": "e23d0246097547e1858aeaf34efe85ef",
"sha256": "ceba61a1b0529b6229ddf4b5a0102a86e6b6e60d4306ed6a2fe5fa5459e8ffbf"
},
"downloads": -1,
"filename": "matrepr-1.0.1.tar.gz",
"has_sig": false,
"md5_digest": "e23d0246097547e1858aeaf34efe85ef",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 36419,
"upload_time": "2024-07-01T05:37:02",
"upload_time_iso_8601": "2024-07-01T05:37:02.181609Z",
"url": "https://files.pythonhosted.org/packages/24/c6/b0efa559db4768544f6b2b2306b7da17f06ebf031f325ca5cbdc7984accc/matrepr-1.0.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-07-01 05:37:02",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "alugowski",
"github_project": "matrepr",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "matrepr"
}