diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2a09829..e73aa35 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,6 +5,11 @@ on: paths-ignore: - '*.md' + # Routinely check that tests pass with new versions of dependencies. + schedule: + # Every day at 17:30 UTC / 9:30 Seattle (winter) / 10:30 Seattle (summer) + - cron: "30 17 * * *" + jobs: build: @@ -12,7 +17,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.8", "3.9", "3.10", "3.11"] + python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] steps: - uses: actions/checkout@v3 diff --git a/CHANGES.md b/CHANGES.md index eaa3d69..44df578 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,13 @@ # CHANGELOG +## 4.0.0 + +### Major Changes + +* Update dependencies, removing hardcoded pins on all dependency versions ([#38][]) + +[#38]: https://github.com/blab/pathogen-embed/pull/38 + ## 3.1.0 ### Features diff --git a/setup.py b/setup.py index 70533f5..0875e45 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ setup( name='pathogen-embed', - version='3.1.0', + version='4.0.0', description='Reduced dimension embeddings for pathogen sequences', url='https://github.com/blab/pathogen-embed/', author='Sravani Nanduri , John Huddleston ', @@ -26,12 +26,9 @@ install_requires=['numpy', 'pandas', "biopython", - 'scikit-learn >=1.3,<1.5', - 'umap-learn ==0.5.*', - # Pin Numba at maximum supported version for the pinned umap-learn version. - # For more details see: - # https://numba.readthedocs.io/en/stable/reference/deprecation.html#deprecation-of-object-mode-fall-back-behaviour-when-using-jit - 'numba <0.59.0', + 'scikit-learn', + 'umap-learn', + 'numba', 'matplotlib', 'hdbscan' ], @@ -45,10 +42,11 @@ 'Intended Audience :: Science/Research', 'License :: OSI Approved :: MIT License', 'Programming Language :: Python :: 3', - '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', + 'Programming Language :: Python :: 3.13', + 'Programming Language :: Python :: 3.14', ], entry_points = { "console_scripts": [ diff --git a/src/pathogen_embed/pathogen_embed.py b/src/pathogen_embed/pathogen_embed.py index 875e9f0..d7fba1a 100644 --- a/src/pathogen_embed/pathogen_embed.py +++ b/src/pathogen_embed/pathogen_embed.py @@ -355,7 +355,9 @@ def embed(args): warnings.simplefilter('ignore', category=NumbaDeprecationWarning) + import packaging.version from scipy.stats import linregress + import sklearn from sklearn.decomposition import PCA from sklearn.manifold import TSNE, MDS from umap import UMAP @@ -540,14 +542,21 @@ def embed(args): elif args.command == "mds": embedding_class = MDS embedding_parameters = { - "dissimilarity": "precomputed", "n_components": n_components, "n_jobs": 1, - "n_init": 2, + "n_init": 1, "random_state" : args.random_seed, "normalized_stress": False, } + if packaging.version.parse(sklearn.__version__) >= packaging.version.parse("1.8"): + # Only use init and metric arguments in later versions of scikit-learn that support them: + # https://scikit-learn.org/stable/modules/generated/sklearn.manifold.MDS.html#sklearn.manifold.MDS + embedding_parameters["init"] = "classical_mds" + embedding_parameters["metric"] = "precomputed" + else: + embedding_parameters["dissimilarity"] = "precomputed" + # Override defaults with parameter values passed through embedding parameters, if # possible. if external_embedding_parameters is not None and args.command != "pca": @@ -634,7 +643,7 @@ def embed(args): fig, ax = plt.subplots(1, 1, figsize=(8, 8), dpi=300) boxplot = ax.boxplot( grouped_euclidean_distances, - labels=list(genetic_distance_range), + tick_labels=list(genetic_distance_range), positions=list(genetic_distance_range), boxprops={ "linewidth": 0.25, @@ -704,7 +713,7 @@ def cluster(args): clusterer = hdbscan.HDBSCAN(**clustering_parameters) data_df = data_df.astype(float) - clusterer.fit(data_df) + clusterer.fit(data_df.values) data_df[args.label_attribute] = clusterer.labels_.astype(str) if args.output_figure is not None: