Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move scipy to optional requirements #1233

Merged
merged 7 commits into from
Jan 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/run_coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ jobs:
- name: Install package with optional dependencies
if: ${{ matrix.opt_req }}
run: |
python -m pip install ".[test,tqdm,zarr,termset]"
python -m pip install ".[test,tqdm,sparse,zarr,termset]"
- name: Run tests and generate coverage report
run: |
Expand Down
2 changes: 1 addition & 1 deletion .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ formats: all
# Optionally set the version of Python and requirements required to build your docs
python:
install:
- path: .[docs,tqdm,zarr,termset] # path to the package relative to the root
- path: .[docs,tqdm,sparse,zarr,termset] # path to the package relative to the root

# Optionally include all submodules
submodules:
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- Importing from `hdmf.build.map` is no longer supported. Import from `hdmf.build` instead. @rly [#1221](https://github.com/hdmf-dev/hdmf/pull/1221)
- Python 3.8 has reached end of life. Dropped support for Python 3.8 and add support for Python 3.13. @mavaylon1 [#1209](https://github.com/hdmf-dev/hdmf/pull/1209)
- Support for Zarr is limited to versions < 3. @rly [#1229](https://github.com/hdmf-dev/hdmf/pull/1229)
- Scipy is no longer a required dependency. Users using the `CSRMatrix` data type should install `scipy` separately or with `pip install "hdmf[sparse]"`. @rly [#1140](https://github.com/hdmf-dev/hdmf/pull/1140)

### Changed
- Added checks to ensure that group and dataset spec names and default names do not contain slashes. @bendichter [#1219](https://github.com/hdmf-dev/hdmf/pull/1219)
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@ dependencies = [
'numpy>=1.19.3',
"pandas>=1.2.0",
"ruamel.yaml>=0.16",
"scipy>=1.7",
]
dynamic = ["version"]

[project.optional-dependencies]
tqdm = ["tqdm>=4.41.0"]
zarr = ["zarr>=2.12.0,<3"]
sparse = ["scipy>=1.7"]
termset = [
"linkml-runtime>=1.5.5",
"schemasheets>=0.1.23",
Expand Down Expand Up @@ -70,7 +70,7 @@ docs = [
]

# all possible dependencies
all = ["hdmf[tqdm,zarr,termset,test,docs]"]
all = ["hdmf[tqdm,zarr,sparse,termset,test,docs]"]

[project.urls]
"Homepage" = "https://github.com/hdmf-dev/hdmf"
Expand Down
22 changes: 17 additions & 5 deletions src/hdmf/common/sparse.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import scipy.sparse as sps
try:
from scipy.sparse import csr_matrix
SCIPY_INSTALLED = True

Check warning on line 3 in src/hdmf/common/sparse.py

View check run for this annotation

Codecov / codecov/patch

src/hdmf/common/sparse.py#L3

Added line #L3 was not covered by tests
except ImportError:
SCIPY_INSTALLED = False
class csr_matrix: # dummy class to prevent import errors
pass

from . import register_class
from ..container import Container
from ..utils import docval, popargs, to_uint_array, get_data_shape, AllowPositional
Expand All @@ -7,7 +14,7 @@
@register_class('CSRMatrix')
class CSRMatrix(Container):

@docval({'name': 'data', 'type': (sps.csr_matrix, 'array_data'),
@docval({'name': 'data', 'type': (csr_matrix, 'array_data'),
'doc': 'the data to use for this CSRMatrix or CSR data array.'
'If passing CSR data array, *indices*, *indptr*, and *shape* must also be provided'},
{'name': 'indices', 'type': 'array_data', 'doc': 'CSR index array', 'default': None},
Expand All @@ -16,13 +23,17 @@
{'name': 'name', 'type': str, 'doc': 'the name to use for this when storing', 'default': 'csr_matrix'},
allow_positional=AllowPositional.WARNING)
def __init__(self, **kwargs):
if not SCIPY_INSTALLED:
raise ImportError(
"scipy must be installed to use CSRMatrix. Please install scipy using `pip install scipy`."
)
data, indices, indptr, shape = popargs('data', 'indices', 'indptr', 'shape', kwargs)
super().__init__(**kwargs)
if not isinstance(data, sps.csr_matrix):
if not isinstance(data, csr_matrix):
temp_shape = get_data_shape(data)
temp_ndim = len(temp_shape)
if temp_ndim == 2:
data = sps.csr_matrix(data)
data = csr_matrix(data)

Check warning on line 36 in src/hdmf/common/sparse.py

View check run for this annotation

Codecov / codecov/patch

src/hdmf/common/sparse.py#L36

Added line #L36 was not covered by tests
elif temp_ndim == 1:
if any(_ is None for _ in (indptr, indices, shape)):
raise ValueError("Must specify 'indptr', 'indices', and 'shape' arguments when passing data array.")
Expand All @@ -31,9 +42,10 @@
shape = self.__check_arr(shape, 'shape')
if len(shape) != 2:
raise ValueError("'shape' argument must specify two and only two dimensions.")
data = sps.csr_matrix((data, indices, indptr), shape=shape)
data = csr_matrix((data, indices, indptr), shape=shape)

Check warning on line 45 in src/hdmf/common/sparse.py

View check run for this annotation

Codecov / codecov/patch

src/hdmf/common/sparse.py#L45

Added line #L45 was not covered by tests
else:
raise ValueError("'data' argument cannot be ndarray of dimensionality > 2.")
# self.__data is a scipy.sparse.csr_matrix
self.__data = data

@staticmethod
Expand Down
22 changes: 19 additions & 3 deletions tests/unit/common/test_sparse.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,25 @@
from hdmf.common import CSRMatrix
from hdmf.testing import TestCase, H5RoundTripMixin

import scipy.sparse as sps
import numpy as np
import unittest

try:
import scipy.sparse as sps
SCIPY_INSTALLED = True
except ImportError:
SCIPY_INSTALLED = False


@unittest.skipIf(SCIPY_INSTALLED, "scipy is installed")
class TestCSRMatrixNoScipy(TestCase):

def test_import_error(self):
data = np.array([[1, 0, 2], [0, 0, 3], [4, 5, 6]])
with self.assertRaises(ImportError):
CSRMatrix(data=data)


@unittest.skipIf(not SCIPY_INSTALLED, "scipy is not installed")
class TestCSRMatrix(TestCase):

def test_from_sparse_matrix(self):
Expand Down Expand Up @@ -153,7 +168,7 @@ def test_array_bad_dim(self):
with self.assertRaisesWith(ValueError, msg):
CSRMatrix(data=data, indices=indices, indptr=indptr, shape=shape)


@unittest.skipIf(not SCIPY_INSTALLED, "scipy is not installed")
class TestCSRMatrixRoundTrip(H5RoundTripMixin, TestCase):

def setUpContainer(self):
Expand All @@ -164,6 +179,7 @@ def setUpContainer(self):
return CSRMatrix(data=data, indices=indices, indptr=indptr, shape=shape)


@unittest.skipIf(not SCIPY_INSTALLED, "scipy is not installed")
class TestCSRMatrixRoundTripFromLists(H5RoundTripMixin, TestCase):
"""Test that CSRMatrix works with lists as well"""

Expand Down
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ extras =
# which optional dependency set(s) to use (default: none)
pytest: test
gallery: doc
optional: tqdm,zarr,termset
optional: tqdm,sparse,zarr,termset
commands =
# commands to run for every environment
python --version # print python version for debugging
Expand Down
Loading