From 2ee3d868eee80293e81bde0aa45f6b82abc8c79e Mon Sep 17 00:00:00 2001 From: Tobias Hangleiter Date: Wed, 19 Jun 2024 11:52:13 +0200 Subject: [PATCH 01/12] Adapt to deprecation --- filter_functions/basis.py | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/filter_functions/basis.py b/filter_functions/basis.py index a69fefd..2aa326a 100644 --- a/filter_functions/basis.py +++ b/filter_functions/basis.py @@ -47,7 +47,6 @@ import numpy as np import opt_einsum as oe from numpy import linalg as nla -from numpy.core import ndarray from scipy import linalg as sla from sparse import COO @@ -56,7 +55,7 @@ __all__ = ['Basis', 'expand', 'ggm_expand', 'normalize'] -class Basis(ndarray): +class Basis(np.ndarray): r""" Class for operator bases. There are several ways to instantiate a Basis object: @@ -217,12 +216,12 @@ def __eq__(self, other: object) -> bool: # Not ndarray return np.equal(self, other) - return np.allclose(self.view(ndarray), other.view(ndarray), + return np.allclose(self.view(np.ndarray), other.view(np.ndarray), atol=self._atol, rtol=self._rtol) - def __contains__(self, item: ndarray) -> bool: + def __contains__(self, item: np.ndarray) -> bool: """Implement 'in' operator.""" - return any(np.isclose(item.view(ndarray), self.view(ndarray), + return any(np.isclose(item.view(np.ndarray), self.view(np.ndarray), rtol=self._rtol, atol=self._atol).all(axis=(1, 2))) def __array_wrap__(self, out_arr, context=None): @@ -232,7 +231,7 @@ def __array_wrap__(self, out_arr, context=None): https://github.com/numpy/numpy/issues/5819#issue-72454838 """ if out_arr.ndim: - return ndarray.__array_wrap__(self, out_arr, context) + return np.ndarray.__array_wrap__(self, out_arr, context) def _print_checks(self) -> None: """Print checks for debug purposes.""" @@ -265,7 +264,7 @@ def isorthonorm(self) -> bool: actual = U.conj() @ U.T target = np.identity(dim) atol = self._eps*(self.d**2)**3 - self._isorthonorm = np.allclose(actual.view(ndarray), target, + self._isorthonorm = np.allclose(actual.view(np.ndarray), target, atol=atol, rtol=self._rtol) return self._isorthonorm @@ -284,7 +283,10 @@ def istraceless(self) -> bool: elif nonzero[0].size == 1: # Single element has nonzero trace, check if (proportional to) # identity - elem = self[nonzero][0].view(ndarray) if self.ndim == 3 else self.view(ndarray) + if self.ndim == 3: + elem = self[nonzero][0].view(np.ndarray) + else: + elem = self.view(np.ndarray) offdiag_nonzero = elem[~np.eye(self.d, dtype=bool)].nonzero() diag_equal = np.diag(elem) == elem[0, 0] if diag_equal.all() and not offdiag_nonzero[0].any(): @@ -597,7 +599,7 @@ def _full_from_partial(elems: Sequence, traceless: bool, labels: Sequence[str]) # sort Identity label to the front, default to first if not found # (should not happen since traceless checks that it is present) id_idx = next((i for i, elem in enumerate(elems) - if np.allclose(Id.view(ndarray), elem.view(ndarray), + if np.allclose(Id.view(np.ndarray), elem.view(np.ndarray), rtol=elems._rtol, atol=elems._atol)), 0) labels.insert(0, labels.pop(id_idx)) @@ -606,7 +608,7 @@ def _full_from_partial(elems: Sequence, traceless: bool, labels: Sequence[str]) return basis, labels -def _norm(b: Sequence) -> ndarray: +def _norm(b: Sequence) -> np.ndarray: """Frobenius norm with two singleton dimensions inserted at the end.""" b = np.asanyarray(b) norm = nla.norm(b, axis=(-1, -2)) @@ -633,8 +635,8 @@ def normalize(b: Basis) -> Basis: return (b/_norm(b)).squeeze().view(Basis) -def expand(M: Union[ndarray, Basis], basis: Union[ndarray, Basis], - normalized: bool = True, hermitian: bool = False, tidyup: bool = False) -> ndarray: +def expand(M: Union[np.ndarray, Basis], basis: Union[np.ndarray, Basis], + normalized: bool = True, hermitian: bool = False, tidyup: bool = False) -> np.ndarray: r""" Expand the array *M* in the basis given by *basis*. @@ -684,8 +686,8 @@ def cast(arr): return util.remove_float_errors(coefficients) if tidyup else coefficients -def ggm_expand(M: Union[ndarray, Basis], traceless: bool = False, - hermitian: bool = False) -> ndarray: +def ggm_expand(M: Union[np.ndarray, Basis], traceless: bool = False, + hermitian: bool = False) -> np.ndarray: r""" Expand the matrix *M* in a Generalized Gell-Mann basis [Bert08]_. This function makes use of the explicit construction prescription of @@ -767,7 +769,7 @@ def cast(arr): return coeffs.squeeze() if square else coeffs -def equivalent_pauli_basis_elements(idx: Union[Sequence[int], int], N: int) -> ndarray: +def equivalent_pauli_basis_elements(idx: Union[Sequence[int], int], N: int) -> np.ndarray: """ Get the indices of the equivalent (up to identities tensored to it) basis elements of Pauli bases of qubits at position idx in the total @@ -780,7 +782,7 @@ def equivalent_pauli_basis_elements(idx: Union[Sequence[int], int], N: int) -> n return elem_idx -def remap_pauli_basis_elements(order: Sequence[int], N: int) -> ndarray: +def remap_pauli_basis_elements(order: Sequence[int], N: int) -> np.ndarray: """ For a N-qubit Pauli basis, transpose the order of the subsystems and return the indices that permute the old basis to the new. From b5d31b1c7092adf12d01d82ea309b38d277d405a Mon Sep 17 00:00:00 2001 From: Tobias Hangleiter Date: Thu, 19 Sep 2024 11:31:38 +0200 Subject: [PATCH 02/12] Relax accuracy --- tests/test_gradient.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_gradient.py b/tests/test_gradient.py index 98499a1..9c060f9 100644 --- a/tests/test_gradient.py +++ b/tests/test_gradient.py @@ -134,7 +134,7 @@ def test_gradient_calculation_random_pulse(self): spectral_noise_density=gradient_testutil.one_over_f_noise, c_id=[f'c{i}' for i in range(len(u_ctrl))], n_coeffs_deriv=None ) - self.assertArrayAlmostEqual(ana_grad, fin_diff_grad, rtol=1e-6, atol=1e-8) + self.assertArrayAlmostEqual(ana_grad, fin_diff_grad, rtol=1e-5, atol=1e-7) def test_caching(self): """Make sure calculation works with or without cached intermediates.""" From 58980af4081be158174bcb648bc75d4cff426946 Mon Sep 17 00:00:00 2001 From: Tobias Hangleiter Date: Mon, 7 Oct 2024 19:06:40 +0200 Subject: [PATCH 03/12] Pin qutip-qtrl version Numpy 2.0 will be fixed above 0.1.3 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 2e85ad3..3dec217 100644 --- a/setup.py +++ b/setup.py @@ -20,7 +20,7 @@ def extract_version(version_file): 'bloch_sphere_visualization': ['qutip', 'matplotlib'], 'fancy_progressbar': ['ipynbname', 'jupyter'], 'doc': ['jupyter', 'nbsphinx', 'numpydoc', 'sphinx', 'sphinx_rtd_theme', - 'ipympl', 'qutip-qip', 'qutip-qtrl'], + 'ipympl', 'qutip-qip', 'qutip-qtrl>0.1.3'], 'tests': ['pytest>=4.6', 'pytest-cov', 'codecov']} extras_require['all'] = list({dep for deps in extras_require.values() for dep in deps}) From ca468332f1a6c644ab8914ad9f947cd96cdb97bf Mon Sep 17 00:00:00 2001 From: Tobias Hangleiter Date: Sun, 13 Oct 2024 15:25:12 +0200 Subject: [PATCH 04/12] Add tests for single-element basis properties --- tests/test_basis.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/tests/test_basis.py b/tests/test_basis.py index 9f5d3e4..c1fd995 100644 --- a/tests/test_basis.py +++ b/tests/test_basis.py @@ -24,12 +24,12 @@ from copy import copy from itertools import product +import filter_functions as ff import numpy as np import pytest -from sparse import COO - -import filter_functions as ff from filter_functions import util +from scipy import stats, linalg +from sparse import COO from tests import testutil from tests.testutil import rng @@ -152,9 +152,15 @@ def test_basis_properties(self): base._print_checks() - basis = util.paulis[1].view(ff.Basis) - self.assertTrue(basis.isorthonorm) - self.assertArrayEqual(basis.T, basis.view(np.ndarray).T) + orthonorm = stats.ortho_group(d).rvs() + self.assertTrue(orthonorm.view(ff.Basis).isorthonorm) + + herm = 1j * linalg.logm(stats.unitary_group(d).rvs()) + self.assertTrue(herm.view(ff.Basis).isherm) + + traceless = stats.multivariate_normal().rvs((d, d)) + traceless -= traceless.trace() / d + self.assertTrue(traceless.view(ff.Basis).istraceless) def test_transpose(self): arr = rng.normal(size=(2, 3, 3)) From 46ab275acaf3958feaa6d33d37d44fbe26da3e8b Mon Sep 17 00:00:00 2001 From: Tobias Hangleiter Date: Sun, 13 Oct 2024 16:10:48 +0200 Subject: [PATCH 05/12] Actually do that --- tests/test_basis.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tests/test_basis.py b/tests/test_basis.py index c1fd995..5da71c1 100644 --- a/tests/test_basis.py +++ b/tests/test_basis.py @@ -152,16 +152,22 @@ def test_basis_properties(self): base._print_checks() - orthonorm = stats.ortho_group(d).rvs() + # single element always considered orthonormal + orthonorm = rng.normal(size=(d, d)) self.assertTrue(orthonorm.view(ff.Basis).isorthonorm) - herm = 1j * linalg.logm(stats.unitary_group(d).rvs()) + herm = testutil.rand_herm(d).squeeze() self.assertTrue(herm.view(ff.Basis).isherm) - traceless = stats.multivariate_normal().rvs((d, d)) - traceless -= traceless.trace() / d + herm[0, 1] += 1 + self.assertFalse(herm.view(ff.Basis).isherm) + + traceless = testutil.rand_herm_traceless(d).squeeze() self.assertTrue(traceless.view(ff.Basis).istraceless) + traceless[0, 0] += 1 + self.assertFalse(traceless.view(ff.Basis).istraceless) + def test_transpose(self): arr = rng.normal(size=(2, 3, 3)) b = arr.view(ff.Basis) From d118ac104acd61113a9847922ef2c721968ab526 Mon Sep 17 00:00:00 2001 From: Tobias Hangleiter Date: Wed, 16 Oct 2024 15:11:16 +0200 Subject: [PATCH 06/12] Drop ipynbname --- filter_functions/util.py | 32 ++++++++++++++++++++------------ setup.py | 1 - tests/test_extras.py | 12 +----------- 3 files changed, 21 insertions(+), 24 deletions(-) diff --git a/filter_functions/util.py b/filter_functions/util.py index 3be1d98..f9704a3 100644 --- a/filter_functions/util.py +++ b/filter_functions/util.py @@ -26,8 +26,7 @@ :func:`abs2` Absolute value squared :func:`get_indices_from_identifiers` - The the indices of a subset of identifiers within a list of - identifiers. + The indices of a subset of identifiers within a list of identifiers. :func:`tensor` Fast, flexible tensor product of an arbitrary number of inputs using :func:`~numpy.einsum` @@ -70,6 +69,7 @@ import functools import inspect import operator +import os import string from itertools import zip_longest from typing import Callable, Iterable, List, Optional, Sequence, Tuple, Union @@ -79,17 +79,25 @@ from .types import Operator, State -try: - import ipynbname - _NOTEBOOK_NAME = ipynbname.name() -except (ImportError, IndexError, FileNotFoundError): - _NOTEBOOK_NAME = '' -if _NOTEBOOK_NAME: - from tqdm.notebook import tqdm as _tqdm +def _in_notebook_kernel(): + # https://github.com/jupyterlab/jupyterlab/issues/16282 + return 'JPY_SESSION_NAME' in os.environ and os.environ['JPY_SESSION_NAME'].endswith('.ipynb') + + +def _in_jupyter_kernel(): + # https://discourse.jupyter.org/t/how-to-know-from-python-script-if-we-are-in-jupyterlab/23993 + return 'JPY_PARENT_PID' in os.environ + + +if not _in_notebook_kernel(): + if _in_jupyter_kernel(): + # (10/24) Autonotebook gets confused in jupyter consoles + from tqdm.std import tqdm + else: + from tqdm.autonotebook import tqdm else: - # Either not running notebook or not able to determine - from tqdm import tqdm as _tqdm + from tqdm.notebook import tqdm __all__ = ['paulis', 'abs2', 'all_array_equal', 'dot_HS', 'get_sample_frequencies', 'hash_array_along_axis', 'mdot', 'oper_equiv', 'progressbar', 'remove_float_errors', @@ -1067,7 +1075,7 @@ def progressbar(iterable: Iterable, *args, **kwargs): for i in progressbar(range(10)): do_something() """ - return _tqdm(iterable, *args, **kwargs) + return tqdm(iterable, *args, **kwargs) def progressbar_range(*args, show_progressbar: bool = True, **kwargs): diff --git a/setup.py b/setup.py index 2e85ad3..6a92a91 100644 --- a/setup.py +++ b/setup.py @@ -18,7 +18,6 @@ def extract_version(version_file): extras_require = {'plotting': ['matplotlib'], 'bloch_sphere_visualization': ['qutip', 'matplotlib'], - 'fancy_progressbar': ['ipynbname', 'jupyter'], 'doc': ['jupyter', 'nbsphinx', 'numpydoc', 'sphinx', 'sphinx_rtd_theme', 'ipympl', 'qutip-qip', 'qutip-qtrl'], 'tests': ['pytest>=4.6', 'pytest-cov', 'codecov']} diff --git a/tests/test_extras.py b/tests/test_extras.py index f27ef2b..61fdd99 100644 --- a/tests/test_extras.py +++ b/tests/test_extras.py @@ -31,21 +31,11 @@ from . import matplotlib -all_extras = ['fancy_progressbar', 'plotting', 'bloch_sphere_visualization'] +all_extras = ['plotting', 'bloch_sphere_visualization'] class MissingExtrasTest(testutil.TestCase): - @pytest.mark.skipif( - 'fancy_progressbar' in os.environ.get('INSTALL_EXTRAS', all_extras), - reason='Skipping tests for missing fancy progressbar extra in build with ipynbname') - def test_fancy_progressbar_not_available(self): - from tqdm import tqdm - - from filter_functions import util - self.assertEqual(util._NOTEBOOK_NAME, '') - self.assertIs(tqdm, util._tqdm) - @pytest.mark.skipif( any(extra in os.environ.get('INSTALL_EXTRAS', all_extras) for extra in ['plotting', 'bloch_sphere_visualization']), From c87a7b64b1769b592f9e03b99aa05877f07c5ac7 Mon Sep 17 00:00:00 2001 From: Tobias Hangleiter Date: Thu, 24 Oct 2024 22:36:34 +0200 Subject: [PATCH 07/12] Adapt to __array_wrap__ deprecation --- filter_functions/basis.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/filter_functions/basis.py b/filter_functions/basis.py index 2aa326a..bf47b49 100644 --- a/filter_functions/basis.py +++ b/filter_functions/basis.py @@ -224,14 +224,18 @@ def __contains__(self, item: np.ndarray) -> bool: return any(np.isclose(item.view(np.ndarray), self.view(np.ndarray), rtol=self._rtol, atol=self._atol).all(axis=(1, 2))) - def __array_wrap__(self, out_arr, context=None): + def __array_wrap__(self, arr, context=None, return_scalar=False): """ Fixes problem that ufuncs return 0-d arrays instead of scalars. https://github.com/numpy/numpy/issues/5819#issue-72454838 """ - if out_arr.ndim: - return np.ndarray.__array_wrap__(self, out_arr, context) + try: + return super().__array_wrap__(arr, context, return_scalar=True) + except TypeError: + if arr.ndim: + # Numpy < 2 + return np.ndarray.__array_wrap__(self, arr, context) def _print_checks(self) -> None: """Print checks for debug purposes.""" From f9f0adfe769ad49a90b91ccee9f4a978663205f6 Mon Sep 17 00:00:00 2001 From: Tobias Hangleiter Date: Thu, 24 Oct 2024 22:37:32 +0200 Subject: [PATCH 08/12] Adapt to nonzero 0d deprecation --- filter_functions/basis.py | 2 +- tests/test_basis.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/filter_functions/basis.py b/filter_functions/basis.py index bf47b49..97f14ea 100644 --- a/filter_functions/basis.py +++ b/filter_functions/basis.py @@ -281,7 +281,7 @@ def istraceless(self) -> bool: if self._istraceless is None: trace = np.einsum('...jj', self) trace = util.remove_float_errors(trace, self.d**2) - nonzero = trace.nonzero() + nonzero = np.atleast_1d(trace).nonzero() if nonzero[0].size == 0: self._istraceless = True elif nonzero[0].size == 1: diff --git a/tests/test_basis.py b/tests/test_basis.py index 5da71c1..edfacb1 100644 --- a/tests/test_basis.py +++ b/tests/test_basis.py @@ -28,7 +28,6 @@ import numpy as np import pytest from filter_functions import util -from scipy import stats, linalg from sparse import COO from tests import testutil from tests.testutil import rng From 09e186c2dccf619d25cac90443bf1f562dbc957f Mon Sep 17 00:00:00 2001 From: Tobias Hangleiter Date: Tue, 5 Nov 2024 19:51:17 +0100 Subject: [PATCH 09/12] Temporarily pin numpy in doc --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 3dec217..8b268a8 100644 --- a/setup.py +++ b/setup.py @@ -20,7 +20,7 @@ def extract_version(version_file): 'bloch_sphere_visualization': ['qutip', 'matplotlib'], 'fancy_progressbar': ['ipynbname', 'jupyter'], 'doc': ['jupyter', 'nbsphinx', 'numpydoc', 'sphinx', 'sphinx_rtd_theme', - 'ipympl', 'qutip-qip', 'qutip-qtrl>0.1.3'], + 'ipympl', 'qutip-qip', 'qutip-qtrl', 'numpy<2'], 'tests': ['pytest>=4.6', 'pytest-cov', 'codecov']} extras_require['all'] = list({dep for deps in extras_require.values() for dep in deps}) From 8f0e1f347d509eb9d72419e7cd914b8353411b10 Mon Sep 17 00:00:00 2001 From: Tobias Hangleiter Date: Wed, 6 Nov 2024 22:04:34 +0100 Subject: [PATCH 10/12] Drop defaults channel --- environment.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/environment.yml b/environment.yml index 018eb5f..60f7de2 100644 --- a/environment.yml +++ b/environment.yml @@ -1,7 +1,6 @@ name: filter_functions channels: - - defaults - conda-forge dependencies: From 430d2c65e6f91fbfcbebf2cb0a5685efef3aff83 Mon Sep 17 00:00:00 2001 From: Tobias Hangleiter Date: Wed, 6 Nov 2024 22:04:43 +0100 Subject: [PATCH 11/12] Drop removed extra --- .readthedocs.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.readthedocs.yml b/.readthedocs.yml index dcabba2..cad158a 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -16,7 +16,6 @@ python: - doc - plotting - bloch_sphere_visualization - - fancy_progressbar sphinx: builder: html From 6938315f3c3a7a16f628f1c95c4b9330fbcf8146 Mon Sep 17 00:00:00 2001 From: Tobias Hangleiter Date: Wed, 6 Nov 2024 23:13:14 +0100 Subject: [PATCH 12/12] Fix autodoc --- doc/source/api.rst | 8 ++++ doc/source/conf.py | 5 +- doc/source/filter_functions.rst | 85 --------------------------------- doc/source/index.rst | 2 +- environment.yml | 1 + setup.py | 2 +- 6 files changed, 14 insertions(+), 89 deletions(-) create mode 100644 doc/source/api.rst delete mode 100644 doc/source/filter_functions.rst diff --git a/doc/source/api.rst b/doc/source/api.rst new file mode 100644 index 0000000..8c71620 --- /dev/null +++ b/doc/source/api.rst @@ -0,0 +1,8 @@ +API +=== + +.. autosummary:: + :toctree: generated + :recursive: + + filter_functions diff --git a/doc/source/conf.py b/doc/source/conf.py index cf630d8..89e80c7 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -38,6 +38,7 @@ 'nbsphinx', 'sphinx.ext.mathjax', 'sphinx.ext.todo', + 'sphinx.ext.autodoc', 'sphinx.ext.autosummary', 'numpydoc', 'sphinx.ext.extlinks', @@ -45,13 +46,12 @@ 'sphinx.ext.ifconfig', 'sphinx.ext.napoleon', 'sphinx.ext.intersphinx', - #'sphinxcontrib.apidoc', + 'sphinxcontrib.apidoc', #'IPython.sphinxext.ipython_console_highlighting', #'IPython.sphinxext.ipython_directive', #'matplotlib.sphinxext.only_directives', #'matplotlib.sphinxext.plot_directive', #'matplotlib.sphinxext.mathmpl', - #'sphinx.ext.autodoc', #'sphinx.ext.doctest', ] @@ -59,6 +59,7 @@ apidoc_module_dir = '../../filter_functions' apidoc_excluded_paths = ['../tests'] apidoc_separate_modules = True +apidoc_module_first = True # Numpydoc settings numpydoc_show_inherited_class_members = False diff --git a/doc/source/filter_functions.rst b/doc/source/filter_functions.rst deleted file mode 100644 index 0c4efd6..0000000 --- a/doc/source/filter_functions.rst +++ /dev/null @@ -1,85 +0,0 @@ -filter\_functions package -========================= - -Submodules ----------- - -filter\_functions.analytic module ---------------------------------- - -.. automodule:: filter_functions.analytic - :members: - :undoc-members: - :show-inheritance: - -filter\_functions.basis module ------------------------------- - -.. automodule:: filter_functions.basis - :members: - :undoc-members: - :show-inheritance: - -filter\_functions.gradient module ---------------------------------- - -.. automodule:: filter_functions.gradient - :members: - :undoc-members: - :show-inheritance: - -filter\_functions.numeric module --------------------------------- - -.. automodule:: filter_functions.numeric - :members: - :undoc-members: - :show-inheritance: - -filter\_functions.plotting module ---------------------------------- - -.. automodule:: filter_functions.plotting - :members: - :undoc-members: - :show-inheritance: - -filter\_functions.pulse\_sequence module ----------------------------------------- - -.. automodule:: filter_functions.pulse_sequence - :members: - :undoc-members: - :show-inheritance: - -filter\_functions.superoperator module --------------------------------------- - -.. automodule:: filter_functions.superoperator - :members: - :undoc-members: - :show-inheritance: - -filter\_functions.types module ------------------------------- - -.. automodule:: filter_functions.types - :members: - :undoc-members: - :show-inheritance: - -filter\_functions.util module ------------------------------ - -.. automodule:: filter_functions.util - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: filter_functions - :members: - :undoc-members: - :show-inheritance: diff --git a/doc/source/index.rst b/doc/source/index.rst index 1101d48..b787bc9 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -23,7 +23,7 @@ Documentation :numbered: examples/examples - filter_functions API Documentation + filter_functions API Documentation Indices and tables ================== diff --git a/environment.yml b/environment.yml index 60f7de2..2c97499 100644 --- a/environment.yml +++ b/environment.yml @@ -6,6 +6,7 @@ channels: dependencies: - python >= 3.9 - qutip + - pandoc - pip prefix: /home/docs/.conda/envs/filter_functions diff --git a/setup.py b/setup.py index 4e0e643..dabcadf 100644 --- a/setup.py +++ b/setup.py @@ -19,7 +19,7 @@ def extract_version(version_file): extras_require = {'plotting': ['matplotlib'], 'bloch_sphere_visualization': ['qutip', 'matplotlib'], 'doc': ['jupyter', 'nbsphinx', 'numpydoc', 'sphinx', 'sphinx_rtd_theme', - 'ipympl', 'qutip-qip', 'qutip-qtrl', 'numpy<2'], + 'sphinxcontrib-apidoc', 'ipympl', 'qutip-qip', 'qutip-qtrl', 'numpy<2'], 'tests': ['pytest>=4.6', 'pytest-cov', 'codecov']} extras_require['all'] = list({dep for deps in extras_require.values() for dep in deps})