diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml index d48f280..6f63c7b 100644 --- a/.github/workflows/run_tests.yml +++ b/.github/workflows/run_tests.yml @@ -21,13 +21,13 @@ jobs: fail-fast: false matrix: config: - - {name: 'current', os: ubuntu-latest, python: '3.8' } + - {name: 'current', os: ubuntu-latest, python: '3.9' } steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.config.python }} @@ -54,14 +54,14 @@ jobs: fail-fast: false matrix: config: + - {name: '3.13', os: ubuntu-latest, python: '3.13' } + - {name: '3.12', os: ubuntu-latest, python: '3.12' } - {name: '3.11', os: ubuntu-latest, python: '3.11' } - {name: '3.10', os: ubuntu-latest, python: '3.10' } - {name: '3.9', os: ubuntu-latest, python: '3.9' } - - {name: '3.8', os: ubuntu-latest, python: '3.8' } - - {name: '3.7', os: ubuntu-latest, python: '3.7' } steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: fetch-depth: 0 @@ -72,12 +72,12 @@ jobs: sudo apt-get install -y libhdf5-dev libhdf5-serial-dev pandoc gfortran libblas-dev liblapack-dev libedit-dev llvm-dev libcurl4-openssl-dev ffmpeg - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.config.python }} - name: Cache Python packages - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: ${{ env.pythonLocation }} key: ${{runner.os}}-${{ matrix.config.python }}-pip-${{ env.pythonLocation }}-${{ hashFiles('setup.py') }} @@ -88,24 +88,26 @@ jobs: cd Python python -m pip install --upgrade pip pip install -U wheel setuptools - pip install -U --prefer-binary .[test] + pip install -e .[test] python -c "import phate" - - name: Run tests + - name: Run tests with coverage run: | cd Python - nose2 -vvv + pip install coverage pytest-cov + pytest --cov=. --cov-report=lcov:coverage.lcov -vv - name: Coveralls - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - COVERALLS_SERVICE_NAME: github - run: | - coveralls + uses: coverallsapp/github-action@v2 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + path-to-lcov: Python/coverage.lcov + continue-on-error: true - name: Upload check results on fail if: failure() - uses: actions/upload-artifact@master + uses: actions/upload-artifact@v4 with: name: ${{ matrix.config.name }}_results path: check + \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index e513ebc..0aa908b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,5 @@ language: python python: - - "3.5" - - "3.6" - - "3.7" - "3.8" - "3.9" - "3.10" diff --git a/Python/phate/__init__.py b/Python/phate/__init__.py index e567da1..5ac2ec9 100644 --- a/Python/phate/__init__.py +++ b/Python/phate/__init__.py @@ -2,8 +2,6 @@ from .phate import PHATE import phate.tree -import phate.io -import phate.preprocessing import phate.mds import phate.vne import phate.plot diff --git a/Python/phate/io.py b/Python/phate/io.py deleted file mode 100644 index ad97a7e..0000000 --- a/Python/phate/io.py +++ /dev/null @@ -1,12 +0,0 @@ -# author: Daniel Burkhardt -# (C) 2017 Krishnaswamy Lab GPLv2 - -from __future__ import print_function, division -import warnings -import scprep -from deprecated import deprecated - - -@deprecated(version="1.0.0", reason="Use scprep.io.load_10X instead") -def load_10X(data_dir, sparse=True, gene_labels="symbol"): - return scprep.io.load_10X(data_dir, sparse=sparse, gene_labels=gene_labels) diff --git a/Python/phate/mds.py b/Python/phate/mds.py index 1b424ea..c1a0128 100644 --- a/Python/phate/mds.py +++ b/Python/phate/mds.py @@ -10,7 +10,6 @@ from deprecated import deprecated import tasklogger -import scprep _logger = tasklogger.get_tasklogger("graphtools") @@ -74,7 +73,13 @@ def sgd(D, n_components=2, random_state=None, init=None): ------- Y : array-like, embedded data [n_sample, ndim] """ - return smacof(D=D, n_components=n_components, random_state=random_state, init=init, metric=True) + return smacof( + D=D, + n_components=n_components, + random_state=random_state, + init=init, + metric=True, + ) def smacof( diff --git a/Python/phate/phate.py b/Python/phate/phate.py index 7db124b..4fb608a 100644 --- a/Python/phate/phate.py +++ b/Python/phate/phate.py @@ -179,7 +179,7 @@ def __init__( n_jobs=1, random_state=None, verbose=1, - **kwargs + **kwargs, ): if "k" in kwargs: warnings.warn("k is deprecated. Please use knn in future.", FutureWarning) @@ -835,7 +835,7 @@ def fit(self, X): n_jobs=self.n_jobs, verbose=self.verbose, random_state=self.random_state, - **(self.kwargs) + **(self.kwargs), ) # landmark op doesn't build unless forced diff --git a/Python/phate/plot.py b/Python/phate/plot.py index 5f5a356..ee891f8 100644 --- a/Python/phate/plot.py +++ b/Python/phate/plot.py @@ -4,9 +4,6 @@ # Plotting convenience functions from __future__ import print_function, division from .phate import PHATE -import warnings -import scprep -from deprecated import deprecated try: import anndata @@ -51,518 +48,3 @@ def _get_plot_data(data, ndim=None): ) ) return out - - -@deprecated(version="1.0.0", reason="Use scprep.plot.scatter instead") -def scatter( - x, - y, - z=None, - c=None, - cmap=None, - s=None, - discrete=None, - ax=None, - legend=None, - figsize=None, - xticks=False, - yticks=False, - zticks=False, - xticklabels=True, - yticklabels=True, - zticklabels=True, - label_prefix="PHATE", - xlabel=None, - ylabel=None, - zlabel=None, - title=None, - legend_title="", - legend_loc="best", - filename=None, - dpi=None, - **plot_kwargs -): - """Create a scatter plot - - Builds upon `matplotlib.pyplot.scatter` with nice defaults - and handles categorical colors / legends better. For easy access, use - `scatter2d` or `scatter3d`. - - Parameters - ---------- - x : list-like - data for x axis - y : list-like - data for y axis - z : list-like, optional (default: None) - data for z axis - c : list-like or None, optional (default: None) - Color vector. Can be a single color value (RGB, RGBA, or named - matplotlib colors), an array of these of length n_samples, or a list of - discrete or continuous values of any data type. If `c` is not a single - or list of matplotlib colors, the values in `c` will be used to - populate the legend / colorbar with colors from `cmap` - cmap : `matplotlib` colormap, str, dict or None, optional (default: None) - matplotlib colormap. If None, uses `tab20` for discrete data and - `inferno` for continuous data. If a dictionary, expects one key - for every unique value in `c`, where values are valid matplotlib colors - (hsv, rbg, rgba, or named colors) - s : float, optional (default: 1) - Point size. - discrete : bool or None, optional (default: None) - If True, the legend is categorical. If False, the legend is a colorbar. - If None, discreteness is detected automatically. Data containing - non-numeric `c` is always discrete, and numeric data with 20 or less - unique values is discrete. - ax : `matplotlib.Axes` or None, optional (default: None) - axis on which to plot. If None, an axis is created - legend : bool, optional (default: True) - States whether or not to create a legend. If data is continuous, - the legend is a colorbar. - figsize : tuple, optional (default: None) - Tuple of floats for creation of new `matplotlib` figure. Only used if - `ax` is None. - xticks : True, False, or list-like (default: False) - If True, keeps default x ticks. If False, removes x ticks. - If a list, sets custom x ticks - yticks : True, False, or list-like (default: False) - If True, keeps default y ticks. If False, removes y ticks. - If a list, sets custom y ticks - zticks : True, False, or list-like (default: False) - If True, keeps default z ticks. If False, removes z ticks. - If a list, sets custom z ticks. Only used for 3D plots. - xticklabels : True, False, or list-like (default: True) - If True, keeps default x tick labels. If False, removes x tick labels. - If a list, sets custom x tick labels - yticklabels : True, False, or list-like (default: True) - If True, keeps default y tick labels. If False, removes y tick labels. - If a list, sets custom y tick labels - zticklabels : True, False, or list-like (default: True) - If True, keeps default z tick labels. If False, removes z tick labels. - If a list, sets custom z tick labels. Only used for 3D plots. - label_prefix : str or None (default: "PHATE") - Prefix for all axis labels. Axes will be labelled `label_prefix`1, - `label_prefix`2, etc. Can be overriden by setting `xlabel`, - `ylabel`, and `zlabel`. - xlabel : str or None (default : None) - Label for the x axis. Overrides the automatic label given by - label_prefix. If None and label_prefix is None, no label is set. - ylabel : str or None (default : None) - Label for the y axis. Overrides the automatic label given by - label_prefix. If None and label_prefix is None, no label is set. - zlabel : str or None (default : None) - Label for the z axis. Overrides the automatic label given by - label_prefix. If None and label_prefix is None, no label is set. - Only used for 3D plots. - title : str or None (default: None) - axis title. If None, no title is set. - legend_title : str (default: "") - title for the colorbar of legend. Only used for discrete data. - legend_loc : int or string or pair of floats, default: 'best' - Matplotlib legend location. Only used for discrete data. - See - for details. - filename : str or None (default: None) - file to which the output is saved - dpi : int or None, optional (default: None) - The resolution in dots per inch. If None it will default to the value - savefig.dpi in the matplotlibrc file. If 'figure' it will set the dpi - to be the value of the figure. Only used if filename is not None. - **plot_kwargs : keyword arguments - Extra arguments passed to `matplotlib.pyplot.scatter`. - - Returns - ------- - ax : `matplotlib.Axes` - axis on which plot was drawn - - Examples - -------- - >>> import phate - >>> import matplotlib.pyplot as plt - >>> ### - >>> # Running PHATE - >>> ### - >>> tree_data, tree_clusters = phate.tree.gen_dla(n_dim=100, n_branch=20, - ... branch_length=100) - >>> tree_data.shape - (2000, 100) - >>> phate_operator = phate.PHATE(k=5, a=20, t=150) - >>> tree_phate = phate_operator.fit_transform(tree_data) - >>> tree_phate.shape - (2000, 2) - >>> ### - >>> # Plotting using phate.plot - >>> ### - >>> phate.plot.scatter2d(tree_phate, c=tree_clusters) - >>> # You can also pass the PHATE operator instead of data - >>> phate.plot.scatter2d(phate_operator, c=tree_clusters) - >>> phate.plot.scatter3d(phate_operator, c=tree_clusters) - >>> ### - >>> # Using a cmap dictionary - >>> ### - >>> import numpy as np - >>> X = np.random.normal(0,1,[1000,2]) - >>> c = np.random.choice(['a','b'], 1000, replace=True) - >>> X[c=='a'] += 10 - >>> phate.plot.scatter2d(X, c=c, cmap={'a' : [1,0,0,1], 'b' : 'xkcd:sky blue'}) - """ - return scprep.plot.scatter( - x=x, - y=y, - z=z, - c=c, - cmap=cmap, - s=s, - discrete=discrete, - ax=ax, - legend=legend, - figsize=figsize, - xticks=xticks, - yticks=yticks, - zticks=zticks, - xticklabels=xticklabels, - yticklabels=yticklabels, - zticklabels=zticklabels, - label_prefix=label_prefix, - xlabel=xlabel, - ylabel=ylabel, - zlabel=zlabel, - title=title, - legend_title=legend_title, - legend_loc=legend_loc, - filename=filename, - dpi=dpi, - **plot_kwargs - ) - - -@deprecated(version="1.0.0", reason="Use scprep.plot.scatter2d instead") -def scatter2d(data, **kwargs): - """Create a 2D scatter plot - - Builds upon `matplotlib.pyplot.scatter` with nice defaults - and handles categorical colors / legends better. - - Parameters - ---------- - data : array-like, shape=[n_samples, n_features] - Input data. Only the first two components will be used. - c : list-like or None, optional (default: None) - Color vector. Can be a single color value (RGB, RGBA, or named - matplotlib colors), an array of these of length n_samples, or a list of - discrete or continuous values of any data type. If `c` is not a single - or list of matplotlib colors, the values in `c` will be used to - populate the legend / colorbar with colors from `cmap` - cmap : `matplotlib` colormap, str, dict or None, optional (default: None) - matplotlib colormap. If None, uses `tab20` for discrete data and - `inferno` for continuous data. If a dictionary, expects one key - for every unique value in `c`, where values are valid matplotlib colors - (hsv, rbg, rgba, or named colors) - s : float, optional (default: 1) - Point size. - discrete : bool or None, optional (default: None) - If True, the legend is categorical. If False, the legend is a colorbar. - If None, discreteness is detected automatically. Data containing - non-numeric `c` is always discrete, and numeric data with 20 or less - unique values is discrete. - ax : `matplotlib.Axes` or None, optional (default: None) - axis on which to plot. If None, an axis is created - legend : bool, optional (default: True) - States whether or not to create a legend. If data is continuous, - the legend is a colorbar. - figsize : tuple, optional (default: None) - Tuple of floats for creation of new `matplotlib` figure. Only used if - `ax` is None. - xticks : True, False, or list-like (default: False) - If True, keeps default x ticks. If False, removes x ticks. - If a list, sets custom x ticks - yticks : True, False, or list-like (default: False) - If True, keeps default y ticks. If False, removes y ticks. - If a list, sets custom y ticks - zticks : True, False, or list-like (default: False) - If True, keeps default z ticks. If False, removes z ticks. - If a list, sets custom z ticks. Only used for 3D plots. - xticklabels : True, False, or list-like (default: True) - If True, keeps default x tick labels. If False, removes x tick labels. - If a list, sets custom x tick labels - yticklabels : True, False, or list-like (default: True) - If True, keeps default y tick labels. If False, removes y tick labels. - If a list, sets custom y tick labels - zticklabels : True, False, or list-like (default: True) - If True, keeps default z tick labels. If False, removes z tick labels. - If a list, sets custom z tick labels. Only used for 3D plots. - label_prefix : str or None (default: "PHATE") - Prefix for all axis labels. Axes will be labelled `label_prefix`1, - `label_prefix`2, etc. Can be overriden by setting `xlabel`, - `ylabel`, and `zlabel`. - xlabel : str or None (default : None) - Label for the x axis. Overrides the automatic label given by - label_prefix. If None and label_prefix is None, no label is set. - ylabel : str or None (default : None) - Label for the y axis. Overrides the automatic label given by - label_prefix. If None and label_prefix is None, no label is set. - zlabel : str or None (default : None) - Label for the z axis. Overrides the automatic label given by - label_prefix. If None and label_prefix is None, no label is set. - Only used for 3D plots. - title : str or None (default: None) - axis title. If None, no title is set. - legend_title : str (default: "") - title for the colorbar of legend - legend_loc : int or string or pair of floats, default: 'best' - Matplotlib legend location. Only used for discrete data. - See - for details. - filename : str or None (default: None) - file to which the output is saved - dpi : int or None, optional (default: None) - The resolution in dots per inch. If None it will default to the value - savefig.dpi in the matplotlibrc file. If 'figure' it will set the dpi - to be the value of the figure. Only used if filename is not None. - **plot_kwargs : keyword arguments - Extra arguments passed to `matplotlib.pyplot.scatter`. - - Returns - ------- - ax : `matplotlib.Axes` - axis on which plot was drawn - - Examples - -------- - >>> import phate - >>> import matplotlib.pyplot as plt - >>> ### - >>> # Running PHATE - >>> ### - >>> tree_data, tree_clusters = phate.tree.gen_dla(n_dim=100, n_branch=20, - ... branch_length=100) - >>> tree_data.shape - (2000, 100) - >>> phate_operator = phate.PHATE(k=5, a=20, t=150) - >>> tree_phate = phate_operator.fit_transform(tree_data) - >>> tree_phate.shape - (2000, 2) - >>> ### - >>> # Plotting using phate.plot - >>> ### - >>> phate.plot.scatter2d(tree_phate, c=tree_clusters) - >>> # You can also pass the PHATE operator instead of data - >>> phate.plot.scatter2d(phate_operator, c=tree_clusters) - >>> phate.plot.scatter3d(phate_operator, c=tree_clusters) - >>> ### - >>> # Using a cmap dictionary - >>> ### - >>> import numpy as np - >>> X = np.random.normal(0,1,[1000,2]) - >>> c = np.random.choice(['a','b'], 1000, replace=True) - >>> X[c=='a'] += 10 - >>> phate.plot.scatter2d(X, c=c, cmap={'a' : [1,0,0,1], 'b' : 'xkcd:sky blue'}) - """ - data = _get_plot_data(data, ndim=2) - return scprep.plot.scatter2d(data, **kwargs) - - -@deprecated(version="1.0.0", reason="Use scprep.plot.scatter3d instead") -def scatter3d(data, **kwargs): - """Create a 3D scatter plot - - Builds upon `matplotlib.pyplot.scatter` with nice defaults - and handles categorical colors / legends better. - - Parameters - ---------- - data : array-like, shape=[n_samples, n_features] - to be the value of the figure. Only used if filename is not None. - Input data. Only the first three components will be used. - c : list-like or None, optional (default: None) - Color vector. Can be a single color value (RGB, RGBA, or named - matplotlib colors), an array of these of length n_samples, or a list of - discrete or continuous values of any data type. If `c` is not a single - or list of matplotlib colors, the values in `c` will be used to - populate the legend / colorbar with colors from `cmap` - cmap : `matplotlib` colormap, str, dict or None, optional (default: None) - matplotlib colormap. If None, uses `tab20` for discrete data and - `inferno` for continuous data. If a dictionary, expects one key - for every unique value in `c`, where values are valid matplotlib colors - (hsv, rbg, rgba, or named colors) - s : float, optional (default: 1) - Point size. - discrete : bool or None, optional (default: None) - If True, the legend is categorical. If False, the legend is a colorbar. - If None, discreteness is detected automatically. Data containing - non-numeric `c` is always discrete, and numeric data with 20 or less - unique values is discrete. - ax : `matplotlib.Axes` or None, optional (default: None) - axis on which to plot. If None, an axis is created - legend : bool, optional (default: True) - States whether or not to create a legend. If data is continuous, - the legend is a colorbar. - figsize : tuple, optional (default: None) - Tuple of floats for creation of new `matplotlib` figure. Only used if - `ax` is None. - xticks : True, False, or list-like (default: False) - If True, keeps default x ticks. If False, removes x ticks. - If a list, sets custom x ticks - yticks : True, False, or list-like (default: False) - If True, keeps default y ticks. If False, removes y ticks. - If a list, sets custom y ticks - zticks : True, False, or list-like (default: False) - If True, keeps default z ticks. If False, removes z ticks. - If a list, sets custom z ticks. Only used for 3D plots. - xticklabels : True, False, or list-like (default: True) - If True, keeps default x tick labels. If False, removes x tick labels. - If a list, sets custom x tick labels - yticklabels : True, False, or list-like (default: True) - If True, keeps default y tick labels. If False, removes y tick labels. - If a list, sets custom y tick labels - zticklabels : True, False, or list-like (default: True) - If True, keeps default z tick labels. If False, removes z tick labels. - If a list, sets custom z tick labels. Only used for 3D plots. - label_prefix : str or None (default: "PHATE") - Prefix for all axis labels. Axes will be labelled `label_prefix`1, - `label_prefix`2, etc. Can be overriden by setting `xlabel`, - `ylabel`, and `zlabel`. - xlabel : str or None (default : None) - Label for the x axis. Overrides the automatic label given by - label_prefix. If None and label_prefix is None, no label is set. - ylabel : str or None (default : None) - Label for the y axis. Overrides the automatic label given by - label_prefix. If None and label_prefix is None, no label is set. - zlabel : str or None (default : None) - Label for the z axis. Overrides the automatic label given by - label_prefix. If None and label_prefix is None, no label is set. - Only used for 3D plots. - title : str or None (default: None) - axis title. If None, no title is set. - legend_title : str (default: "") - title for the colorbar of legend - legend_loc : int or string or pair of floats, default: 'best' - Matplotlib legend location. Only used for discrete data. - See - for details. - filename : str or None (default: None) - file to which the output is saved - dpi : int or None, optional (default: None) - The resolution in dots per inch. If None it will default to the value - savefig.dpi in the matplotlibrc file. If 'figure' it will set the dpi - to be the value of the figure. Only used if filename is not None. - **plot_kwargs : keyword arguments - Extra arguments passed to `matplotlib.pyplot.scatter`. - - Returns - ------- - ax : `matplotlib.Axes` - axis on which plot was drawn - - Examples - -------- - >>> import phate - >>> import matplotlib.pyplot as plt - >>> ### - >>> # Running PHATE - >>> ### - >>> tree_data, tree_clusters = phate.tree.gen_dla(n_dim=100, n_branch=20, - ... branch_length=100) - >>> tree_data.shape - (2000, 100) - >>> phate_operator = phate.PHATE(k=5, a=20, t=150) - >>> tree_phate = phate_operator.fit_transform(tree_data) - >>> tree_phate.shape - (2000, 2) - >>> ### - >>> # Plotting using phate.plot - >>> ### - >>> phate.plot.scatter2d(tree_phate, c=tree_clusters) - >>> # You can also pass the PHATE operator instead of data - >>> phate.plot.scatter2d(phate_operator, c=tree_clusters) - >>> phate.plot.scatter3d(phate_operator, c=tree_clusters) - >>> ### - >>> # Using a cmap dictionary - >>> ### - >>> import numpy as np - >>> X = np.random.normal(0,1,[1000,2]) - >>> c = np.random.choice(['a','b'], 1000, replace=True) - >>> X[c=='a'] += 10 - >>> phate.plot.scatter2d(X, c=c, cmap={'a' : [1,0,0,1], 'b' : 'xkcd:sky blue'}) - """ - data = _get_plot_data(data, ndim=3) - return scprep.plot.scatter3d(data, **kwargs) - - -@deprecated(version="1.0.0", reason="Use scprep.plot.rotate_scatter3d instead") -def rotate_scatter3d( - data, - filename=None, - elev=30, - rotation_speed=30, - fps=10, - ax=None, - figsize=None, - dpi=None, - ipython_html="jshtml", - **kwargs -): - """Create a rotating 3D scatter plot - - Builds upon `matplotlib.pyplot.scatter` with nice defaults - and handles categorical colors / legends better. - - Parameters - ---------- - data : array-like, `phate.PHATE` or `scanpy.AnnData` - Input data. Only the first three dimensions are used. - filename : str, optional (default: None) - If not None, saves a .gif or .mp4 with the output - elev : float, optional (default: 30) - Elevation of viewpoint from horizontal, in degrees - rotation_speed : float, optional (default: 30) - Speed of axis rotation, in degrees per second - fps : int, optional (default: 10) - Frames per second. Increase this for a smoother animation - ax : `matplotlib.Axes` or None, optional (default: None) - axis on which to plot. If None, an axis is created - figsize : tuple, optional (default: None) - Tuple of floats for creation of new `matplotlib` figure. Only used if - `ax` is None. - dpi : number, optional (default: None) - Controls the dots per inch for the movie frames. This combined with - the figure's size in inches controls the size of the movie. - If None, defaults to rcParams["savefig.dpi"] - ipython_html : {'html5', 'jshtml'} - which html writer to use if using a Jupyter Notebook - **kwargs : keyword arguments - See :~func:`phate.plot.scatter3d`. - - Returns - ------- - ani : `matplotlib.animation.FuncAnimation` - animation object - - Examples - -------- - >>> import phate - >>> import matplotlib.pyplot as plt - >>> tree_data, tree_clusters = phate.tree.gen_dla(n_dim=100, n_branch=20, - ... branch_length=100) - >>> tree_data.shape - (2000, 100) - >>> phate_operator = phate.PHATE(n_components=3, k=5, a=20, t=150) - >>> tree_phate = phate_operator.fit_transform(tree_data) - >>> tree_phate.shape - (2000, 2) - >>> phate.plot.rotate_scatter3d(tree_phate, c=tree_clusters) - """ - data = _get_plot_data(data, ndim=3) - return scprep.plot.rotate_scatter3d( - data, - filename=filename, - elev=elev, - rotation_speed=rotation_speed, - fps=fps, - ax=ax, - figsize=figsize, - dpi=dpi, - ipython_html=ipython_html, - **kwargs - ) diff --git a/Python/phate/preprocessing.py b/Python/phate/preprocessing.py deleted file mode 100644 index 01fb4d0..0000000 --- a/Python/phate/preprocessing.py +++ /dev/null @@ -1,14 +0,0 @@ -# author: Daniel Burkhardt -# (C) 2017 Krishnaswamy Lab GPLv2 - -from __future__ import print_function, division -import warnings -import scprep -from deprecated import deprecated - - -@deprecated( - version="1.0.0", reason="Use scprep.normalize.library_size_normalize instead" -) -def library_size_normalize(data, verbose=False): - return scprep.normalize.library_size_normalize(data) diff --git a/Python/phate/version.py b/Python/phate/version.py index 9eb1ebe..bd538f7 100644 --- a/Python/phate/version.py +++ b/Python/phate/version.py @@ -1 +1 @@ -__version__ = "1.0.11" +__version__ = "1.0.12" diff --git a/Python/pyproject.toml b/Python/pyproject.toml new file mode 100644 index 0000000..00ceffe --- /dev/null +++ b/Python/pyproject.toml @@ -0,0 +1,65 @@ +[build-system] +requires = ["setuptools>=61.0", "wheel"] +build-backend = "setuptools.build_meta" + +[project] +name = "phate" +dynamic = ["version"] +description = "PHATE" +authors = [ + {name = "Daniel Burkhardt, Krishnaswamy Lab, Yale University", email = "daniel.burkhardt@yale.edu"} +] +license = {text = "GNU General Public License Version 2"} +readme = "README.md" +requires-python = ">=3.9" +dependencies = [ + "numpy>=1.20.0", + "scipy>=1.7.0", + "scikit-learn>=1.5.0", + "future", + "tasklogger>=1.2", + "graphtools>=2.0.0", + "Deprecated", + "matplotlib>=3.0", +] +keywords = [ + "visualization", + "big-data", + "dimensionality-reduction", + "embedding", + "manifold-learning", + "computational-biology", +] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Environment :: Console", + "Framework :: Jupyter", + "Intended Audience :: Developers", + "Intended Audience :: Science/Research", + "Natural Language :: English", + "Operating System :: MacOS :: MacOS X", + "Operating System :: Microsoft :: Windows", + "Operating System :: POSIX :: Linux", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Topic :: Scientific/Engineering :: Bio-Informatics", + "Topic :: Scientific/Engineering :: Visualization", +] + +[tool.setuptools.dynamic] +version = {attr = "phate.version.__version__"} + +[project.urls] +Homepage = "https://github.com/KrishnaswamyLab/PHATE" +Repository = "https://github.com/KrishnaswamyLab/PHATE" +Download = "https://github.com/KrishnaswamyLab/PHATE/archive/v{version}.tar.gz" + +[project.optional-dependencies] +test = ["pytest", "anndata", "coverage", "coveralls"] +doc = ["sphinx", "sphinxcontrib-napoleon"] + + +[tool.setuptools.packages.find] \ No newline at end of file diff --git a/Python/requirements.txt b/Python/requirements.txt deleted file mode 100644 index ac01c3d..0000000 --- a/Python/requirements.txt +++ /dev/null @@ -1,9 +0,0 @@ -numpy<=1.26.4 -scipy>=1.1.0 -scikit-learn>=0.20.0 -future -tasklogger>=1.0 -graphtools>=1.3.1 -scprep>=1.0 -matplotlib>=3.0 -Deprecated diff --git a/Python/setup.py b/Python/setup.py deleted file mode 100644 index 2a17a61..0000000 --- a/Python/setup.py +++ /dev/null @@ -1,82 +0,0 @@ -import os -import sys -from setuptools import setup, find_packages - -install_requires = [ - "numpy<=1.26.4", - "scipy>=1.1.0", - "scikit-learn>=0.20.0", - "future", - "tasklogger>=1.2", - "graphtools>=1.5.3", - "scprep>=0.11.1", - "Deprecated", -] - -test_requires = ["nose2", "anndata", "coverage", "coveralls", "nose"] - -doc_requires = ["sphinx", "sphinxcontrib-napoleon"] - -version_py = os.path.join(os.path.dirname(__file__), "phate", "version.py") -version = open(version_py).read().strip().split("=")[-1].replace('"', "").strip() - -if sys.version_info[:2] < (3, 5): - raise RuntimeError("Python version >=3.5 required.") -elif sys.version_info[:2] < (3, 6): - install_requires += ["matplotlib>=3.0,<3.1"] -else: - install_requires += ["matplotlib>=3.0"] - -readme = open("README.md").read() - -setup( - name="phate", - version=version, - description="PHATE", - author="Daniel Burkhardt, Krishnaswamy Lab, Yale University", - author_email="daniel.burkhardt@yale.edu", - packages=find_packages(), - license="GNU General Public License Version 2", - install_requires=install_requires, - extras_require={"test": test_requires, "doc": doc_requires}, - test_suite="nose2.collector.collector", - long_description=readme, - long_description_content_type="text/markdown", - url="https://github.com/KrishnaswamyLab/PHATE", - download_url="https://github.com/KrishnaswamyLab/PHATE/archive/v{}.tar.gz".format( - version - ), - keywords=[ - "visualization", - "big-data", - "dimensionality-reduction", - "embedding", - "manifold-learning", - "computational-biology", - ], - classifiers=[ - "Development Status :: 5 - Production/Stable", - "Environment :: Console", - "Framework :: Jupyter", - "Intended Audience :: Developers", - "Intended Audience :: Science/Research", - "Natural Language :: English", - "Operating System :: MacOS :: MacOS X", - "Operating System :: Microsoft :: Windows", - "Operating System :: POSIX :: Linux", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.5", - "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - "Topic :: Scientific/Engineering :: Bio-Informatics", - "Topic :: Scientific/Engineering :: Visualization", - ], -) - -# get location of setup.py -setup_dir = os.path.dirname(os.path.realpath(__file__)) diff --git a/Python/test/test.py b/Python/test/test_simple.py similarity index 57% rename from Python/test/test.py rename to Python/test/test_simple.py index f9284b1..8178b95 100644 --- a/Python/test/test.py +++ b/Python/test/test_simple.py @@ -7,8 +7,7 @@ import matplotlib matplotlib.use("Agg") # noqa -import scprep -import nose2 + import os import phate import graphtools @@ -17,18 +16,11 @@ import numpy as np from scipy.spatial.distance import pdist, squareform -from nose.tools import assert_raises_regex, assert_warns_regex import re +import pytest -def assert_warns_message(expected_warning, expected_message, *args, **kwargs): - expected_regex = re.escape(expected_message) - return assert_warns_regex(expected_warning, expected_regex, *args, **kwargs) - - -def assert_raises_message(expected_warning, expected_message, *args, **kwargs): - expected_regex = re.escape(expected_message) - return assert_raises_regex(expected_warning, expected_regex, *args, **kwargs) +import warnings def test_simple(): @@ -59,9 +51,7 @@ def test_simple(): G = pygsp.graphs.Graph(G.W) phate_operator.fit(G) phate_operator.fit(anndata.AnnData(tree_data)) - with assert_raises_message( - TypeError, "Expected phate_op to be of type PHATE. Got 1" - ): + with pytest.raises(TypeError, match="Expected phate_op to be of type PHATE. Got 1"): phate.cluster.kmeans(1) @@ -142,77 +132,5 @@ def test_tree(): return 0 -def test_bmmsc(): - data_dir = os.path.join("..", "data") - if not os.path.isdir(data_dir): - data_dir = os.path.join("..", data_dir) - clusters = scprep.io.load_csv( - os.path.join(data_dir, "MAP.csv"), gene_names=["clusters"] - ) - bmmsc = scprep.io.load_csv(os.path.join(data_dir, "BMMC_myeloid.csv.gz")) - - C = clusters["clusters"] # using cluster labels from original publication - - # library_size_normalize performs L1 normalization on each cell - bmmsc_norm = scprep.normalize.library_size_normalize(bmmsc) - bmmsc_norm = scprep.transform.sqrt(bmmsc_norm) - phate_fast_operator = phate.PHATE( - n_components=2, - t="auto", - decay=200, - knn=10, - mds="metric", - mds_dist="euclidean", - n_landmark=1000, - verbose=False, - ) - - print("BMMSC, fast PHATE") - Y_mmds_fast = phate_fast_operator.fit_transform(bmmsc_norm, t_max=100) - assert Y_mmds_fast.shape == (bmmsc_norm.shape[0], 2) - return 0 - - -def test_plot(): - tree_data, tree_clusters = phate.tree.gen_dla() - # scatter - assert_warns_message( - DeprecationWarning, - "Call to deprecated function (or staticmethod) scatter. (Use scprep.plot.scatter instead) -- Deprecated since version 1.0.0.", - phate.plot.scatter, - tree_data[:, 0], - tree_data[:, 1], - c=tree_clusters, - discrete=True, - ) - # scatter2d - assert_warns_message( - DeprecationWarning, - "Call to deprecated function (or staticmethod) scatter2d. (Use scprep.plot.scatter2d instead) -- Deprecated since version 1.0.0.", - phate.plot.scatter2d, - tree_data, - c=tree_clusters, - discrete=True, - ) - # scatter3d - assert_warns_message( - DeprecationWarning, - "Call to deprecated function (or staticmethod) scatter3d. (Use scprep.plot.scatter3d instead) -- Deprecated since version 1.0.0.", - phate.plot.scatter3d, - tree_data, - c=tree_clusters, - discrete=False, - ) - # rotate_scatter3d - assert_warns_message( - DeprecationWarning, - "Call to deprecated function (or staticmethod) rotate_scatter3d. (Use scprep.plot.rotate_scatter3d instead) -- Deprecated since version 1.0.0.", - phate.plot.rotate_scatter3d, - tree_data, - c=tree_clusters, - discrete=False, - ) - - if __name__ == "__main__": - exit(nose2.run()) + pytest.main([__file__])