From 6b33964da815b3e686a0f069f67580c5acbff045 Mon Sep 17 00:00:00 2001 From: Guillaume Tauzin Date: Thu, 21 May 2020 07:53:47 +0200 Subject: [PATCH] Release v0.3.1 (#41) * Fix docstring typo * Fix format of output diagram (#38) * Fix format of output diagram Signed-off-by: Guillaume Tauzin * Add auditwheel repair and twine check, remove tarball from CI (#40) * Wording tweaks in README, removal of gcc install step * Remove trailing whitespace * Create release notes for v0.2.1, bump version * Remove source distribution, use auditwheel repair on manylinux, add twine check * Update for v0.3.1 (#39) * Update for v0.3.1 Signed-off-by: Guillaume Tauzin * Fix rst typos * Retroactively fix more rst typos in RELEASE.rst * Final round of typo fixes in RELEASE.rst * Fix issue with boldfacing in RELEASE.rst * Problematic spaces removes from RELEASE.rst * Retroactively fix problematic spaces in RELEASE.rst Co-authored-by: Umberto Lupo <46537483+ulupo@users.noreply.github.com> --- .azure-ci/docker_scripts.sh | 9 +++- RELEASE.rst | 93 +++++++++++++++++++++++++------------ azure-pipelines.yml | 10 +++- pyflagser/_version.py | 2 +- pyflagser/flagio.py | 2 +- pyflagser/flagser.py | 27 +++++------ setup.py | 2 +- 7 files changed, 96 insertions(+), 49 deletions(-) diff --git a/.azure-ci/docker_scripts.sh b/.azure-ci/docker_scripts.sh index 9f12458..17054c2 100644 --- a/.azure-ci/docker_scripts.sh +++ b/.azure-ci/docker_scripts.sh @@ -22,5 +22,10 @@ flake8 --exit-zero /io/ pip uninstall -y pyflagser # Build wheels -pip install wheel -python setup.py sdist bdist_wheel +pip install wheel==0.34.1 auditwheel==3.1.0 +python setup.py bdist_wheel + +# Repair wheels with auditwheel +auditwheel repair dist/*whl -w dist/ +# remove wheels that are not manylinux2010 +rm -rf dist/*-linux*.whl diff --git a/RELEASE.rst b/RELEASE.rst index 5e08acd..54ba407 100644 --- a/RELEASE.rst +++ b/RELEASE.rst @@ -1,3 +1,31 @@ +Release 0.3.1 +============== + +Major Features and Improvements +------------------------------- +- Clarity of the code of ``flagser_unweighted`` and ``flagser_weighted`` was improved. +- Auditwheel repair is now run in the manylinux jobs. +- ``twine check`` is now run as part of the CI. + +Bug Fixes +--------- +- Fix bug causing ``flagser_weighted``'s output persistence diagrams to be a list of list of tuples instead of a list of ``numpy.ndarrays`` of shape (n_points, 2). + +Backwards-Incompatible Changes +------------------------------ +- Installation from tarballs is no longer supported. + +Thanks to our Contributors +-------------------------- + +This release contains contributions from many people: + +Umberto Lupo and Guillaume Tauzin. + +We are also grateful to all who filed issues or helped resolve them, asked and +answered questions, and were part of inspiring discussions. + + Release 0.3.0 ============== @@ -6,49 +34,56 @@ Major Features and Improvements This is a major release. The whole library has been fully refactored and all functions have been renamed. In particular: -- All functions have been split into an `unweighted` and a `weighted` version. +- All functions have been split into an ``unweighted`` and a ``weighted`` version. - - The `unweighted` functions process unweighted graphs. In the adjacency matrices passed to them, off-diagonal, ``0`` or ``False`` values denote absent edges while non-``0`` or ``True`` values denote edges which are present. Diagonal values are ignored. - - The `weighted` functions process weighted graphs. In the adjacency matrices passed to them, the way zero values are handled depends on the format of the matrix. If the matrix is a dense ``numpy.ndarray``, zero values denote zero-weighted edges. If the matrix is a sparse ``scipy.sparse`` matrix, explicitly stored off-diagonal zeros and all diagonal zeros denote zero-weighted edges. Off-diagonal values that have not been explicitely stored are treated by ``scipy.sparse`` as zeros but will be understood as infinitely-valued edges, i.e., edges absent from the filtration. Diagonal elements are vertex weights. - -- `saveflag` has been split into `save_unweighted_flag` and a `save_weighted_flag`: + - The ``unweighted`` functions process unweighted graphs. In the adjacency matrices passed to them, off-diagonal, ``0`` or ``False`` values denote absent edges while non-``0`` or ``True`` values denote edges which are present. Diagonal values are ignored. + - The ``weighted`` functions process weighted graphs. In the adjacency matrices passed to them, the way zero values are handled depends on the format of the matrix. If the matrix is a dense ``numpy.ndarray``, zero values denote zero-weighted edges. If the matrix is a sparse ``scipy.sparse`` matrix, explicitly stored off-diagonal zeros and all diagonal zeros denote zero-weighted edges. Off-diagonal values that have not been explicitely stored are treated by ``scipy.sparse`` as zeros but will be understood as infinitely-valued edges, i.e., edges absent from the filtration. Diagonal elements are vertex weights. - - `save_unweighted_flag` focuses on saving adjacency matrices of unweighted graphs into a `.flag` file understandable by C++ `flagser`. - - `save_weighted_flag` focuses on saving adjacency matrices of weighted graphs into a `.flag` file understandable by C++ `flagser`. It now takes a `max_edge_weight` argument. All edge weights greater than that value will be considered as infinitely-valued, i.e., absent from the filtration. - -- `loadflag` has been split into `load_unweighted_flag` and a `load_weighted_flag`. +- ``saveflag`` has been split into ``save_unweighted_flag`` and a ``save_weighted_flag``: - - `load_unweighted_flag` focuses on loading `.flag` files as adjacency matrices of unweighted graphs. - - `load_weighted_flag` focuses on loading `.flag` files as adjacency matrices of weighted graphs. It now take an `infinity_value` parameter which is the value to use to denote an absence of edge. It is only useful when the output adjacency matrix is set to be a ``numpy.ndarray`` by passing `fmt` as ``'dense``. If ``None``, it is set to the maximum value allowed by the passed `dtype`. - -- `flagser` has been split into `flagser_unweighted` and a `flagser_weighted`. + - ``save_unweighted_flag`` focuses on saving adjacency matrices of unweighted graphs into a `.flag` file understandable by C++ `flagser`. + - ``save_weighted_flag`` focuses on saving adjacency matrices of weighted graphs into a `.flag` file understandable by C++ `flagser`. It now takes a ``max_edge_weight`` argument. All edge weights greater than that value will be considered as infinitely-valued, i.e., absent from the filtration. - - `flagser_unweighted` focuses on the computation of homology and outputs Betti numbers, cell counts per dimension, and Euler characteristic. - - `flagser_weighted` focuses on the computation of persistent homology and outputs persistence diagrams, Betti numbers, cell counts per dimension, and Euler characteristic. It now takes a `max_edge_weight` argument. All edge weights greater than that value will be considered as infinitely-valued, i.e., absent from the filtration. +- ``loadflag`` has been split into ``load_unweighted_flag`` and a ``load_weighted_flag``. + + - ``load_unweighted_flag`` focuses on loading ``.flag`` files as adjacency matrices of unweighted graphs. + - ``load_weighted_flag`` focuses on loading ``.flag`` files as adjacency matrices of weighted graphs. It now take an ``infinity_value`` parameter which is the value to use to denote an absence of edge. It is only useful when the output adjacency matrix is set to be a ``numpy.ndarray`` by passing `fmt` as ``'dense'``. If ``None``, it is set to the maximum value allowed by the passed `dtype`. + +- ``flagser`` has been split into ``flagser_unweighted`` and a ``flagser_weighted``. + + - ``flagser_unweighted`` focuses on the computation of homology and outputs Betti numbers, cell counts per dimension, and Euler characteristic. + - ``flagser_weighted`` focuses on the computation of persistent homology and outputs persistence diagrams, Betti numbers, cell counts per dimension, and Euler characteristic. It now takes a ``max_edge_weight`` argument. All edge weights greater than that value will be considered as infinitely-valued, i.e., absent from the filtration. Additionally, - - The documentation have been strongly improved both in docstrings and in the code. - - The handling of default parameters has been improved and warnings are now issued. - - Sparse matrix efficiency warnings have been turned off (`lil_matrix` cannot be used because it ignores explicitly set 0 values). - - Core functions to transform an adjacency matrix into the data structures understood by C++ `flagser` have been moved to the new `_utils.py`. - - Tests have been extended according to cover the new functionalities. + +- The documentation have been strongly improved both in docstrings and in the code. +- The handling of default parameters has been improved and warnings are now issued. +- Sparse matrix efficiency warnings have been turned off (``lil_matrix`` cannot be used because it ignores explicitly set 0 values). +- Core functions to transform an adjacency matrix into the data structures understood by C++ ``flagser`` have been moved to the new ``_utils.py``. +- Tests have been extended according to cover the new functionalities. Bug Fixes --------- The following bug fixes were introduced: - - A bug fix from C++ `flagser` on ``vertex_degree`` filtration has been propagated to pyflagser. - - A bug in the C++ `flagser` bindings causing persistence diagrams and cell counts to be wrong based on the values of `min_dimension` and `max_dimension` has been fixed. - - Tests were updated accordingly and `conftest.py` has been improved. - - Bugs in the `pyflagser` `flagser` functions causing incompatibilities with sparse matrix and non-float datatype have been fixed. - - ``CMakeLists`` has been updated to use C++14. This addresses problem when compiling on MacOS. + +- A bug fix from C++ ``flagser`` on ``vertex_degree`` filtration has been propagated to pyflagser. + +- A bug in the C++ ``flagser`` bindings causing persistence diagrams and cell counts to be wrong based on the values of ``min_dimension`` and ``max_dimension`` has been fixed. + +- Tests were updated accordingly and `conftest.py` has been improved. + +- Bugs in the ``pyflagser`` ``flagser`` functions causing incompatibilities with sparse matrix and non-float datatype have been fixed. + +- ``CMakeLists`` has been updated to use C++14. This addresses problem when compiling on MacOS. Backwards-Incompatible Changes ------------------------------ The library has been fully refactored, which means that most changes were backwards-incompatible. In particular: -- All functions have been renamed as they now include an `unweighted` and a `weighted` version. -- The `flag_matrix` argument have been renamed `adjacency_matrix`. + +- All functions have been renamed as they now include an ``unweighted`` and a ``weighted`` version. +- The ``flag_matrix`` argument have been renamed ``adjacency_matrix``. Please check the documentation for more information. @@ -76,8 +111,8 @@ Bug Fixes Hotfix addressing multiples issues where forwarding arguments to C++ ``flagser``: - - ``filtration`` was not correctly forwarded and it always fallback to zero filtration. - - ``max-dim`` and ``min-dim`` were always equal to 0. +- ``filtration`` was not correctly forwarded and it always fallback to zero filtration. +- ``max-dim`` and ``min-dim`` were always equal to 0. ``CMakeLists`` updated to disable AVX instructions. This addresses incompatibilities observed with specific hardware setups. diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 73ae535..b3f5a72 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -213,10 +213,16 @@ jobs: - script: | pip install wheel - python setup.py sdist bdist_wheel + python setup.py bdist_wheel failOnStderr: false displayName: 'Build the wheels' + - script: | + set -e + pip install twine + twine check dist/* + displayName: 'Check distribution with twine' + - script: pip install dist/*.whl failOnStderr: true displayName: 'Install the wheels' @@ -302,7 +308,7 @@ jobs: - bash: | sed -i $'s/\r$//' README.rst pip install wheel - python setup.py sdist bdist_wheel + python setup.py bdist_wheel failOnStderr: false displayName: 'Build the wheels' diff --git a/pyflagser/_version.py b/pyflagser/_version.py index a270dce..e0b2c89 100644 --- a/pyflagser/_version.py +++ b/pyflagser/_version.py @@ -17,4 +17,4 @@ # 'X.Y.dev0' is the canonical version of 'X.Y.dev' # -__version__ = '0.3.0' +__version__ = '0.3.1' diff --git a/pyflagser/flagio.py b/pyflagser/flagio.py index 0daba6e..ca9ab7d 100644 --- a/pyflagser/flagio.py +++ b/pyflagser/flagio.py @@ -17,7 +17,7 @@ def load_unweighted_flag(fname, fmt='csr', dtype=np.bool): Filename of extension ``.flag`` containing the information of a flag matrix. - fmt : {'dense', 'dia', 'csr', 'csc', 'lil', ...}, optional, + fmt : {'dense', 'dia', 'csr', 'csc', 'lil', ...}, optional, \ default: ``'csr'`` Matrix format of the result. By default, a CSR sparse matrix is returned. Keep in mind that some matrix formats do not track zero diff --git a/pyflagser/flagser.py b/pyflagser/flagser.py index 2b9808d..a801df0 100644 --- a/pyflagser/flagser.py +++ b/pyflagser/flagser.py @@ -93,13 +93,15 @@ def flagser_unweighted(adjacency_matrix, min_dimension=0, max_dimension=np.inf, # Call flagser binding homology = compute_homology(vertices, edges, min_dimension, _max_dimension, - directed, coeff, _approximation, _filtration) + directed, coeff, _approximation, + _filtration)[0] # Creating dictionary of return values - out = dict() - out['betti'] = homology[0].get_betti_numbers() - out['cell_count'] = homology[0].get_cell_count() - out['euler'] = homology[0].get_euler_characteristic() + out = { + 'betti': homology.get_betti_numbers(), + 'cell_count': homology.get_cell_count(), + 'euler': homology.get_euler_characteristic() + } return out @@ -227,14 +229,13 @@ def flagser_weighted(adjacency_matrix, max_edge_weight=None, min_dimension=0, # Call flagser binding homology = compute_homology(vertices, edges, min_dimension, _max_dimension, - directed, coeff, _approximation, filtration) + directed, coeff, _approximation, filtration)[0] # Create dictionary of return values - out = dict() - out['dgms'] = [homology[0].get_persistence_diagram()[i] - for i in range(len(homology[0].get_persistence_diagram()))] - out['betti'] = homology[0].get_betti_numbers() - out['cell_count'] = homology[0].get_cell_count() - out['euler'] = homology[0].get_euler_characteristic() - + out = { + 'dgms': [np.asarray(d) for d in homology.get_persistence_diagram()], + 'betti': homology.get_betti_numbers(), + 'cell_count': homology.get_cell_count(), + 'euler': homology.get_euler_characteristic() + } return out diff --git a/setup.py b/setup.py index 748a2d8..c1e344a 100755 --- a/setup.py +++ b/setup.py @@ -28,7 +28,7 @@ MAINTAINER_EMAIL = 'maintainers@giotto.ai' URL = 'https://github.com/giotto-ai/pyflagser' LICENSE = 'GNU AGPLv3' -DOWNLOAD_URL = 'https://github.com/giotto-ai/pyflagser/tarball/v0.3.0' +DOWNLOAD_URL = 'https://github.com/giotto-ai/pyflagser/tarball/v0.3.1' VERSION = __version__ # noqa CLASSIFIERS = ['Intended Audience :: Science/Research', 'Intended Audience :: Developers',