From 797b99b06d29b70919c8ab1fe29da008a7775e48 Mon Sep 17 00:00:00 2001 From: Scott Gigante Date: Sun, 3 Mar 2019 16:07:37 -0500 Subject: [PATCH] refactor attempted imports --- scprep/io/fcs.py | 20 +++----------------- scprep/io/hdf5.py | 12 ++++-------- scprep/plot/histogram.py | 8 ++++---- scprep/plot/jitter.py | 6 +++--- scprep/plot/marker.py | 4 ++-- scprep/plot/scatter.py | 20 +++++++++----------- scprep/plot/scree.py | 6 ++++-- scprep/plot/style.py | 4 ++-- scprep/plot/tools.py | 19 +++++++++---------- scprep/plot/utils.py | 28 ++++++++-------------------- scprep/stats.py | 7 ++----- scprep/utils.py | 22 +++++++++++++++++++++- 12 files changed, 71 insertions(+), 85 deletions(-) diff --git a/scprep/io/fcs.py b/scprep/io/fcs.py index 5b0a279c..83fadfdb 100644 --- a/scprep/io/fcs.py +++ b/scprep/io/fcs.py @@ -3,29 +3,15 @@ import pandas as pd import numpy as np -from decorator import decorator import struct from io import BytesIO import string import warnings from .utils import _matrix_to_data_frame +from .. import utils -try: - import fcsparser -except ImportError: - pass - - -@decorator -def _with_fcsparser(fun, *args, **kwargs): - try: - fcsparser - except NameError: - raise ImportError( - "fcsparser not found. " - "Please install it with e.g. `pip install --user fcsparser`") - return fun(*args, **kwargs) +fcsparser = utils._try_import("fcsparser") def _channel_names_from_meta(meta, channel_numbers, naming="N"): @@ -236,7 +222,7 @@ def _fcsextract(filename, channel_naming="$PnS", reformat_meta=True): return meta, events -@_with_fcsparser +@utils._with_pkg("fcsparser") def load_fcs(filename, gene_names=True, cell_names=True, sparse=None, metadata_channels=['Time', 'Event_length', 'DNA1', 'DNA2', diff --git a/scprep/io/hdf5.py b/scprep/io/hdf5.py index dcc4743d..32b43fb4 100644 --- a/scprep/io/hdf5.py +++ b/scprep/io/hdf5.py @@ -2,14 +2,10 @@ # (C) 2018 Krishnaswamy Lab GPLv2 from decorator import decorator -try: - import tables -except ImportError: - pass -try: - import h5py -except ImportError: - pass +from .. import utils + +tables = utils._try_import("tables") +h5py = utils._try_import("h5py") @decorator diff --git a/scprep/plot/histogram.py b/scprep/plot/histogram.py index fc44e727..88553351 100644 --- a/scprep/plot/histogram.py +++ b/scprep/plot/histogram.py @@ -2,12 +2,12 @@ import pandas as pd from .. import measure, utils -from .utils import (_with_matplotlib, _get_figure, show, +from .utils import (_get_figure, show, temp_fontsize, parse_fontsize) from .tools import label_axis -@_with_matplotlib +@utils._with_pkg("matplotlib") def histogram(data, bins=100, log=False, cutoff=None, percentile=None, @@ -89,7 +89,7 @@ def histogram(data, return ax -@_with_matplotlib +@utils._with_pkg("matplotlib") def plot_library_size(data, bins=100, log=True, cutoff=None, percentile=None, @@ -146,7 +146,7 @@ def plot_library_size(data, xlabel=xlabel, title=title, fontsize=fontsize, **kwargs) -@_with_matplotlib +@utils._with_pkg("matplotlib") def plot_gene_set_expression(data, genes=None, starts_with=None, ends_with=None, regex=None, bins=100, log=False, diff --git a/scprep/plot/jitter.py b/scprep/plot/jitter.py index 9ce571fa..0af79bc6 100644 --- a/scprep/plot/jitter.py +++ b/scprep/plot/jitter.py @@ -1,8 +1,8 @@ import numpy as np import pandas as pd -from .. import utils, stats, select -from .utils import (_with_matplotlib, _get_figure, show, +from .. import utils +from .utils import (_get_figure, show, temp_fontsize, parse_fontsize, _with_default) from .tools import label_axis, generate_colorbar, generate_legend @@ -26,7 +26,7 @@ def x_coords(self): return self._x_coords[self.plot_idx] -@_with_matplotlib +@utils._with_pkg("matplotlib") def jitter(labels, values, sigma=0.1, c=None, cmap=None, cmap_scale='linear', s=None, diff --git a/scprep/plot/marker.py b/scprep/plot/marker.py index 0f332d5d..088439f0 100644 --- a/scprep/plot/marker.py +++ b/scprep/plot/marker.py @@ -2,12 +2,12 @@ import pandas as pd from .. import utils, stats, select -from .utils import (_with_matplotlib, _get_figure, show, +from .utils import (_get_figure, show, temp_fontsize, parse_fontsize, shift_ticklabels) from .tools import label_axis -@_with_matplotlib +@utils._with_pkg("matplotlib") def marker_plot(data, clusters, markers, gene_names=None, normalize_expression=True, cmap='magma', title=None, figsize=(8, 6), diff --git a/scprep/plot/scatter.py b/scprep/plot/scatter.py index 7cb69823..1e8bdc42 100644 --- a/scprep/plot/scatter.py +++ b/scprep/plot/scatter.py @@ -2,20 +2,18 @@ import numbers import pandas as pd import warnings -try: - import matplotlib.pyplot as plt - import matplotlib as mpl - from matplotlib import animation -except ImportError: - pass from .. import utils, select -from .utils import (_get_figure, _with_matplotlib, _is_color_array, +from .utils import (_get_figure, _is_color_array, show, _in_ipynb, parse_fontsize, temp_fontsize, _with_default) from .tools import (create_colormap, create_normalize, label_axis, generate_colorbar, generate_legend) +plt = utils._try_import("matplotlib.pyplot") +mpl = utils._try_import("matplotlib") +animation = utils._try_import("matplotlib.animation") + class _ScatterParams(object): @@ -350,7 +348,7 @@ def check_cmap_scale(self): self._cmap_scale = 'linear' -@_with_matplotlib +@utils._with_pkg("matplotlib") def scatter(x, y, z=None, c=None, cmap=None, cmap_scale='linear', s=None, discrete=None, ax=None, @@ -556,7 +554,7 @@ def scatter(x, y, z=None, return ax -@_with_matplotlib +@utils._with_pkg("matplotlib") def scatter2d(data, c=None, cmap=None, cmap_scale='linear', s=None, discrete=None, ax=None, legend=None, colorbar=None, @@ -708,7 +706,7 @@ def scatter2d(data, **plot_kwargs) -@_with_matplotlib +@utils._with_pkg("matplotlib") def scatter3d(data, c=None, cmap=None, cmap_scale='linear', s=None, discrete=None, ax=None, legend=None, colorbar=None, @@ -875,7 +873,7 @@ def scatter3d(data, **plot_kwargs) -@_with_matplotlib +@utils._with_pkg("matplotlib") def rotate_scatter3d(data, filename=None, rotation_speed=30, diff --git a/scprep/plot/scree.py b/scprep/plot/scree.py index 1bdc3766..20d793bd 100644 --- a/scprep/plot/scree.py +++ b/scprep/plot/scree.py @@ -1,11 +1,13 @@ import numpy as np -from .utils import (_with_matplotlib, _get_figure, show, +from .. import utils + +from .utils import (_get_figure, show, temp_fontsize) from .tools import label_axis -@_with_matplotlib +@utils._with_pkg("matplotlib") def scree_plot(singular_values, cumulative=False, ax=None, figsize=None, xlabel='Principal Component', ylabel='Explained Variance (%)', fontsize=None, diff --git a/scprep/plot/style.py b/scprep/plot/style.py index e33438c5..031a170f 100644 --- a/scprep/plot/style.py +++ b/scprep/plot/style.py @@ -1,8 +1,8 @@ -from .utils import _with_matplotlib +from .. import utils from .tools import label_axis -@_with_matplotlib +@utils._with_pkg("matplotlib") def style_phate(ax, label_prefix="PHATE"): """Removes ticks from `ax` and adds axis labels. diff --git a/scprep/plot/tools.py b/scprep/plot/tools.py index 25cf89c8..bb08b9a5 100644 --- a/scprep/plot/tools.py +++ b/scprep/plot/tools.py @@ -1,15 +1,14 @@ import numpy as np import warnings -try: - import matplotlib as mpl - import matplotlib.pyplot as plt -except ImportError: - pass -from .utils import _with_matplotlib, _get_figure, parse_fontsize, temp_fontsize +from .. import utils +from .utils import _get_figure, parse_fontsize, temp_fontsize +plt = utils._try_import("matplotlib.pyplot") +mpl = utils._try_import("matplotlib") -@_with_matplotlib + +@utils._with_pkg("matplotlib") def create_colormap(colors, name="scprep_custom_cmap"): """Create a custom colormap from a list of colors @@ -39,7 +38,7 @@ def create_colormap(colors, name="scprep_custom_cmap"): return cmap -@_with_matplotlib +@utils._with_pkg("matplotlib") def create_normalize(vmin, vmax, scale=None): """Create a colormap normalizer @@ -76,7 +75,7 @@ def create_normalize(vmin, vmax, scale=None): return norm -@_with_matplotlib +@utils._with_pkg("matplotlib") def generate_legend(cmap, ax, title=None, marker='o', markersize=10, loc='best', bbox_to_anchor=None, fontsize=None, title_fontsize=None, @@ -133,7 +132,7 @@ def generate_legend(cmap, ax, title=None, marker='o', markersize=10, return legend -@_with_matplotlib +@utils._with_pkg("matplotlib") def generate_colorbar(cmap=None, vmin=None, vmax=None, scale=None, ax=None, title=None, title_rotation=270, fontsize=None, n_ticks='auto', labelpad=10, mappable=None, **kwargs): diff --git a/scprep/plot/utils.py b/scprep/plot/utils.py index f85b4b25..5022209c 100644 --- a/scprep/plot/utils.py +++ b/scprep/plot/utils.py @@ -1,24 +1,11 @@ import numpy as np -from decorator import decorator import platform -try: - import matplotlib.pyplot as plt - import matplotlib as mpl - from mpl_toolkits.mplot3d import Axes3D -except ImportError: - pass +from .. import utils -@decorator -def _with_matplotlib(fun, *args, **kwargs): - try: - assert int(mpl.__version__[0]) >= 3 - except (NameError, AssertionError): - raise ImportError( - "matplotlib>=3.0 not found. " - "Please install it with e.g. " - "`pip install --user --upgrade matplotlib`") - return fun(*args, **kwargs) +plt = utils._try_import("matplotlib.pyplot") +mpl = utils._try_import("matplotlib") +mplot3d = utils._try_import("mpl_toolkits.mplot3d") def _with_default(param, default): @@ -49,7 +36,8 @@ def _get_figure(ax=None, figsize=None, subplot_kw=None): else: raise e if 'projection' in subplot_kw: - if subplot_kw['projection'] == '3d' and not isinstance(ax, Axes3D): + if subplot_kw['projection'] == '3d' and \ + not isinstance(ax, mplot3d.Axes3D): raise TypeError("Expected ax with projection='3d'. " "Got 2D axis instead.") show_fig = False @@ -73,7 +61,7 @@ def _in_ipynb(): return False -@_with_matplotlib +@utils._with_pkg("matplotlib") def show(fig): """Show a matplotlib Figure correctly, regardless of platform @@ -148,7 +136,7 @@ def __exit__(self, type, value, traceback): plt.rcParams['font.size'] = self.old_size -@_with_matplotlib +@utils._with_pkg("matplotlib") def shift_ticklabels(axis, dx=0, dy=0): """Shifts ticklabels on an axis diff --git a/scprep/stats.py b/scprep/stats.py index 4c9e6ba3..6a931429 100644 --- a/scprep/stats.py +++ b/scprep/stats.py @@ -8,10 +8,7 @@ from . import plot, utils import warnings -try: - import matplotlib.pyplot as plt -except ImportError: - pass +plt = utils._try_import("matplotlib.pyplot") def EMD(x, y): @@ -286,7 +283,7 @@ def knnDREMI(x, y, k=10, n_bins=20, n_mesh=3, n_jobs=1, return dremi -@plot.utils._with_matplotlib +@utils._with_pkg("matplotlib") def plot_knnDREMI(dremi, mutual_info, x, y, n_bins, n_mesh, density, bin_density, drevi, figsize=(12, 3.5), filename=None, diff --git a/scprep/utils.py b/scprep/utils.py index 6b1599a8..a63c42af 100644 --- a/scprep/utils.py +++ b/scprep/utils.py @@ -3,10 +3,30 @@ import numbers from scipy import sparse import warnings -import re +import importlib +from decorator import decorator + from . import select +def _try_import(pkg): + try: + return importlib.import_module(pkg) + except ImportError: + return None + + +@decorator +def _with_pkg(fun, pkg=None, *args, **kwargs): + try: + importlib.import_module(pkg) + except ImportError: + raise ImportError( + "{0} not found. " + "Please install it with e.g. `pip install --user {0}`".format(pkg)) + return fun(*args, **kwargs) + + def toarray(x): """Convert an array-like to a np.ndarray