diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 80cebd60..b05328d2 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -380,7 +380,7 @@ or a custom testing template: 1. Normal Cases Test Class: - Name: 'Test[TARGET FUNCTION NAME]'. - Objective: Test EACH parameter *INDIVIDUALLY*. - - Tests: For EACH parameter, at least 10 positive and 10 negative tests. + - Tests: Test EACH parameter, at least 10 positive and 10 negative tests for this class. 2. Complex Cases Test Class: - Name: 'Test[TARGET FUNCTION NAME]Complex'. @@ -400,3 +400,7 @@ or a custom testing template: Reminder: In Normal Cases, it's crucial to test parameters individually. " + +You can run this prompt multiple times or ask to continue. After copy-pasting all results into +your final testing script. Copy this script and provide it to ChatGPT with the prompt to remove +redundancy and to make it more concise. \ No newline at end of file diff --git a/aaanalysis/__pycache__/utils.cpython-39.pyc b/aaanalysis/__pycache__/utils.cpython-39.pyc index 817cb465..7241a923 100644 Binary files a/aaanalysis/__pycache__/utils.cpython-39.pyc and b/aaanalysis/__pycache__/utils.cpython-39.pyc differ diff --git a/aaanalysis/_utils/__pycache__/_utils_check.cpython-39.pyc b/aaanalysis/_utils/__pycache__/_utils_check.cpython-39.pyc index bf44610c..0d2d39d3 100644 Binary files a/aaanalysis/_utils/__pycache__/_utils_check.cpython-39.pyc and b/aaanalysis/_utils/__pycache__/_utils_check.cpython-39.pyc differ diff --git a/aaanalysis/_utils/__pycache__/utils_cpp.cpython-39.pyc b/aaanalysis/_utils/__pycache__/utils_cpp.cpython-39.pyc index b0d9b6af..6e04d252 100644 Binary files a/aaanalysis/_utils/__pycache__/utils_cpp.cpython-39.pyc and b/aaanalysis/_utils/__pycache__/utils_cpp.cpython-39.pyc differ diff --git a/aaanalysis/_utils/_utils_check.py b/aaanalysis/_utils/_utils_check.py index 920fdd84..a7147c68 100644 --- a/aaanalysis/_utils/_utils_check.py +++ b/aaanalysis/_utils/_utils_check.py @@ -6,6 +6,18 @@ # Type checking functions +def check_number_val(name=None, val=None, accept_none=False, just_int=False): + """Check if value is float""" + if just_int is None: + raise ValueError("'just_int' must be specified") + if accept_none and val is None: + return None + valid_types = (int,) if just_int else (float, int) + type_description = "int" if just_int else "float or int" + if not isinstance(val, valid_types): + raise ValueError(f"'{name}' ({val}) should be {type_description})") + + def check_number_range(name=None, val=None, min_val=0, max_val=None, accept_none=False, just_int=None): """Check if value of given name is within defined range""" if just_int is None: @@ -24,22 +36,8 @@ def check_number_range(name=None, val=None, min_val=0, max_val=None, accept_none raise ValueError(error) -def check_number_val(name=None, val=None, accept_none=False, just_int=False): - """Check if value is float""" - check_types = [int] if just_int else [float, int] - if accept_none and val is None: - return None - if type(val) not in [float, int]: - error = f"'{name}' ({val}) should be float" - if not just_int: - error += " or int." - else: - error += "." - raise ValueError(error) - - def check_str(name=None, val=None, accept_none=False): - """""" + """Check type string""" if accept_none and val is None: return None if not isinstance(val, str): @@ -47,37 +45,39 @@ def check_str(name=None, val=None, accept_none=False): def check_bool(name=None, val=None): - """""" - if type(val) != bool: + """Check if the provided value is a boolean.""" + if not isinstance(val, bool): raise ValueError(f"'{name}' ({val}) should be bool.") def check_dict(name=None, val=None, accept_none=False): - """""" - error = f"'{name}' ('{val}') should be a dictionary" - if accept_none: - error += " or None." - else: - error += "." + """Check if the provided value is a dictionary.""" if accept_none and val is None: return None if not isinstance(val, dict): + error = f"'{name}' ({val}) should be a dictionary" + error += " or None." if accept_none else "." raise ValueError(error) -def check_tuple(name=None, val=None, n=None): +def check_tuple(name=None, val=None, n=None, check_n=True): """""" - error = f"'{name}' ('{val}') should be a tuple" - if n is not None: - error += f" with {n} elements." - else: - error += "." if not isinstance(val, tuple): - raise ValueError(error) - if n is not None and len(val) != n: - raise ValueError(error) + raise ValueError(f"'{name}' ({val}) should be a tuple.") + if check_n and n is not None and len(val) != n: + raise ValueError(f"'{name}' ({val}) should be a tuple with {n} elements.") +# Check special types +def check_ax(ax=None, accept_none=False): + """""" + import matplotlib.axes + if accept_none and ax is None: + return None + if not isinstance(ax, matplotlib.axes.Axes): + raise ValueError(f"'ax' (type={type(ax)}) should be mpl.axes.Axes or None.") + +# TODO check these functions if used # Array checking functions def check_feat_matrix(X=None, names=None, labels=None): """Transpose matrix and check if X and y match (y can be labels or names). Transpose back otherwise """ diff --git a/aaanalysis/cpp/__pycache__/cpp_plot.cpython-39.pyc b/aaanalysis/cpp/__pycache__/cpp_plot.cpython-39.pyc index 40670a8c..52e88270 100644 Binary files a/aaanalysis/cpp/__pycache__/cpp_plot.cpython-39.pyc and b/aaanalysis/cpp/__pycache__/cpp_plot.cpython-39.pyc differ diff --git a/aaanalysis/plotting/__pycache__/plot_set_legend_.cpython-39.pyc b/aaanalysis/plotting/__pycache__/plot_set_legend_.cpython-39.pyc index eb404ef8..d65f8102 100644 Binary files a/aaanalysis/plotting/__pycache__/plot_set_legend_.cpython-39.pyc and b/aaanalysis/plotting/__pycache__/plot_set_legend_.cpython-39.pyc differ diff --git a/aaanalysis/plotting/plot_set_legend_.py b/aaanalysis/plotting/plot_set_legend_.py index beda4d8d..4e5c12b8 100644 --- a/aaanalysis/plotting/plot_set_legend_.py +++ b/aaanalysis/plotting/plot_set_legend_.py @@ -5,154 +5,303 @@ import matplotlib as mpl from matplotlib import pyplot as plt from aaanalysis import utils as ut +import matplotlib.lines as mlines + # I Helper functions -# Checking functions -def check_cats(list_cat=None, dict_color=None, labels=None): +# Checking functios +def check_dict_colors(dict_color=None, list_cat=None, labels=None): """""" ut.check_dict(name="dict_color", val=dict_color, accept_none=False) - if labels is not None: - if list_cat is not None: + # If labels are provided + if labels: + # If list_cat is provided, check its length against labels + if list_cat: if len(list_cat) != len(labels): raise ValueError(f"Length of 'list_cat' ({len(list_cat)}) and 'labels' ({len(labels)}) must match") + # If list_cat isn't provided, check the length of dict_color against labels elif len(dict_color) != len(labels): raise ValueError(f"Length of 'dict_color' ({len(dict_color)}) and 'labels' ({len(labels)}) must match") - if list_cat is None: + # Default list_cat to the keys of dict_color if not provided + if not list_cat: list_cat = list(dict_color.keys()) - else: - raise ValueError("'list_cat' and 'dict_color' should not be None") return list_cat -# Helper functions -def _create_marker(color, category, shape, lw, edgecolor): - if shape is None: + +def check_x_y(x=None, y=None): + """""" + ut.check_number_val(name="x", val=x, accept_none=True, just_int=False) + ut.check_number_val(name="y", val=y, accept_none=True, just_int=False) + # Check if matching + if x is None and y is None: + return + if x is not None and y is not None: + return + raise ValueError(f"'x' ({x}) and 'y' ({y}) must either both be None or both given.") + + + +def _check_validity(item, valid_items, item_name, list_cat): + """General check validity function.""" + if item is None: + return [item] * len(list_cat) + item_is_list = isinstance(item, list) + if not item_is_list: + if item not in valid_items: + raise ValueError(f"'{item_name}' ('{item}') must be one of the following: {valid_items}") + else: + return [item] * len(list_cat) + else: + wrong_items = [x for x in item if x not in valid_items] + if len(wrong_items) != 0: + raise ValueError( + f"'{item_name}' contains wrong items ('{wrong_items}')! Must be one of the following: {valid_items}") + if len(item) != len(list_cat): + raise ValueError(f"Length of '{item_name}' ({item}) and categories ({list_cat}) must match!") + else: + return item + + +def check_marker(marker=None, list_cat=None, lw=0): + """Check validity of marker.""" + all_markers = list(mlines.Line2D.markers.keys()) + all_markers.append("-") # Allow '-' as a valid marker for a line + if marker == "-" and lw <= 0: + raise ValueError(f"If marker is '{marker}', 'lw' ({lw}) must be > 0.") + return _check_validity(marker, all_markers, 'marker', list_cat) + + +def check_linestyle(marker_linestyle=None, list_cat=None): + """Check validity of linestyle.""" + _lines = ['-', '--', '-.', ':'] + _names = ["solid", "dashed", "dashed-doted", "dotted"] + dict_names_lines = dict(zip(_names, _lines)) + # Names to line styles + if isinstance(marker_linestyle, str) and marker_linestyle in _names: + marker_linestyle = dict_names_lines[marker_linestyle] + elif isinstance(marker_linestyle, list): + marker_linestyle = [dict_names_lines.get(x, x) for x in marker_linestyle] + valid_linestyles = dict(zip(_lines, _names)) + return _check_validity(marker_linestyle, valid_linestyles, 'marker_linestyle', list_cat) + + +# Helper function +def _create_marker(color, category, marker, marker_size, lw, edgecolor, linestyle='-'): + """Create custom marker based on input.""" + if marker == "-": # If marker is '-', treat it as a line + return plt.Line2D([0, 1], [0, 1], color=color, linestyle=linestyle, lw=lw, label=category) + + if marker is None: args = {'facecolor': color, 'label': category, 'lw': lw} if edgecolor: args['edgecolor'] = edgecolor return mpl.patches.Patch(**args) - return plt.Line2D([0], [0], marker=shape, color='w', markerfacecolor=color, markersize=10, label=category) - + return plt.Line2D([0], [0], marker=marker, color='w', linestyle=linestyle, markerfacecolor=color, + markersize=marker_size, label=category) # II Main function -# TODO check, interface, doc, test def plot_set_legend(ax: Optional[plt.Axes] = None, + remove_legend: bool = True, handles: Optional[List] = None, + return_handles: bool = False, + # Color and Categories dict_color: Optional[Dict[str, str]] = None, list_cat: Optional[List[str]] = None, labels: Optional[List[str]] = None, - y: Optional[int] = None, - x: Optional[int] = None, + # Position and Layout + loc: str = "upper left", + loc_out: bool = False, + y: Optional[Union[int, float]] = None, + x: Optional[Union[int, float]] = None, ncol: int = 3, - fontsize: Optional[int] = None, + labelspacing: Union[int, float] = 0.2, + columnspacing: Union[int, float] = 1.0, + handletextpad: Union[int, float] = 0.8, + handlelength: Union[int, float] = 2, + # Font and Style + fontsize: Optional[Union[int, float]] = None, + fontsize_title: Optional[Union[int, float]] = None, weight: str = "normal", - lw: float = 0, + fontsize_weight: str = "normal", + # Line, Marker, and Area + lw: Union[int, float] = 0, edgecolor: Optional[str] = None, - return_handles: bool = False, - loc: str = "upper left", - labelspacing: float = 0.2, - columnspacing: int = 1, + marker: Optional[Union[str, int, list]] = None, + marker_size: Union[int, float] = 10, + marker_linestyle: Union[str, list] = "-", + # Title title: Optional[str] = None, - fontsize_legend: Optional[int] = None, title_align_left: bool = True, - fontsize_weight: str = "normal", - shape: Optional[str] = None, - **kwargs) -> Union[plt.Axes, Tuple[List, List[str]]]: + **kwargs + ) -> Union[plt.Axes, Tuple[List, List[str]]]: """ Set a customizable legend for a plot. + Legends can be flexbily adjusted based on ``handles`` or categories and colors provided in ``dict_color``. + This functions comprises the most convinient settings for ``func:`matplotlib.pyplot.legend``. + Parameters ---------- ax The axes to attach the legend to. If not provided, the current axes will be used. + remove_legend: + Remove legend of given or current axes. handles - Handles for legend items. If not provided, they will be generated based on `dict_color` and `list_cat`. + Handles for legend items. If not provided, they will be generated based on ``dict_color`` and ``list_cat``. + return_handles + Whether to return handles and labels. If ``True``, function returns ``handles``, ``labels`` instead of the axes. + dict_color A dictionary mapping categories to colors. list_cat - List of categories to include in the legend. + List of categories to include in the legend (keys of ``dict_color``). labels - Labels for legend items. + Labels for legend items corresponding to given categories. + loc + Location for the legend. + loc_out + If ``True``, sets automatically ``x=0`` and ``y=-0.25`` if they are ``None``. y The y-coordinate for the legend's anchor point. x The x-coordinate for the legend's anchor point. ncol Number of columns in the legend. + labelspacing + Vertical spacing between legend items. + columnspacing + Horizontal spacing between legend columns. + handletextpad + Horizontal spacing bewtween legend handle (marker) and label. + handlelength + Length of legend handle (marker). fontsize Font size for the legend text. + fontsize_title + Font size for the legend title. weight Weight of the font. + fontsize_weight + Font weight for the legend title. lw Line width for legend items. edgecolor Edge color for legend items. - return_handles - Whether to return handles and labels. If `True`, function returns `handles, labels` instead of the axes. - loc - Location for the legend. - labelspacing - Vertical spacing between legend items. - columnspacing - Horizontal spacing between legend columns. + marker + Marker shape for legend items. '-' is added to the :mod:`matplotlib` default options to use lines as markers. + marker_size + Marker size for legend items. + marker_linestyle + Marker linestyle of legend items. title Title for the legend. - fontsize_legend - Font size for the legend title. title_align_left Whether to align the title to the left. - fontsize_weight - Font weight for the legend title. - shape - Marker shape for legend items. Refer to `matplotlib.lines.Line2D` for available shapes. + **kwargs + Furhter key word arguments for :func:`matplotlib.axes.Axes.legend`. Returns ------- ax - The axes with the legend applied. If `return_handles=True`, it returns handles and labels instead. + The axes with the legend applied. If ``return_handles=True``, it returns ``handles`` and ``labels`` instead. Examples -------- - >>> import aaanalysis as aa - >>> aa.plot_set_legend(ax=ax, dict_color={'Cat1': 'red', 'Cat2': 'blue'}, shape='o') + .. plot:: + :include-source: + + >>> import matplotlib.pyplot as plt + >>> import seaborn as sns + >>> import aaanalysis as aa + >>> data = {'Classes': ['A', 'B', 'C'], 'Values': [23, 27, 43]} + >>> colors = aa.plot_get_cmap(name="CAT", n_colors=3) + >>> aa.plot_settings() + >>> sns.barplot(x='Classes', y='Values', data=data, palette=colors) + >>> sns.despine() + >>> dict_color = dict(zip(["Class A", "Class B", "Class C"], colors)) + >>> aa.plot_set_legend(dict_color=dict_color, ncol=1, marker="-", lw=10, loc_out=True) + >>> plt.tight_layout() + >>> plt.show() See Also -------- - matplotlib.pyplot.legend - For additional details on how the 'loc' parameter can be customized. - matplotlib.lines.Line2D - For details on the different types of marker shapes ('shape' parameter). + * `Matplotlib markers `. + * `Linestyles of markers ` + * :func:`matplotlib.lines.Line2D` for available marker shapes and line properties. + * :func:`matplotlib.axes.Axes`, which is the core object in matplotlib. + * :func:`matplotlib.pyplot.gca` to get the current Axes instance. """ - - # Check input + # Check basic input + ut.check_ax(ax=ax, accept_none=True) if ax is None: ax = plt.gca() - list_cat = check_cats(list_cat=list_cat, dict_color=dict_color, labels=labels) - args_float = {"y": y, "x": x, "lw": lw, "labelspacing": labelspacing, - "columnspacing": columnspacing} - for key in args_float: - ut.check_number_val(name=key, val=args_float[key], just_int=False) - ut.check_number_range(name="ncol", val=ncol, min_val=1, just_int=True, accept_none=True) + + ut.check_bool(name="remove_current_legend", val=remove_legend) ut.check_bool(name="return_handles", val=return_handles) ut.check_bool(name="title_align_left", val=title_align_left) + ut.check_bool(name="loc_out", val=loc_out) - # TODO check other args - # Generate legend items if not provided - if not handles and dict_color and list_cat: - handles = [_create_marker(dict_color[cat], cat, shape, lw, edgecolor) for cat in list_cat] + ut.check_number_range(name="ncol", val=ncol, min_val=1, accept_none=True, just_int=True) + args_float = {"labelspacing": labelspacing, "columnspacing": columnspacing, + "handletextpad": handletextpad, "handlelength": handlelength, + "fontsize": fontsize, "fontsize_legend": fontsize_title, + "lw": lw, "marker_size": marker_size} + for key in args_float: + ut.check_number_val(name=key, val=args_float[key], accept_none=True, just_int=False) + check_x_y(x=x, y=y) - # Return handles and labels if required - if return_handles: - return handles, labels if labels else list_cat - # Set up legend properties - labels = labels or list_cat - args = dict(prop={"weight": weight, "size": fontsize}, **kwargs) - if fontsize_legend: - args["title_fontproperties"] = {"weight": fontsize_weight, "size": fontsize_legend} + # Set y an x if legend should be outside + if loc_out: + x = x if x is not None else 0 + y = y if y is not None else -0.25 + + # Universal Legend Arguments + args = dict(loc=loc, + ncol=ncol, + fontsize=fontsize, + labelspacing=labelspacing, + columnspacing=columnspacing, + handletextpad=handletextpad, + handlelength=handlelength, + borderpad=0, # Fractional whitespace inside the legend border. + title=title, + edgecolor=edgecolor, + prop={"weight": weight, "size": fontsize}) + args.update(kwargs) + if fontsize_title: + args["title_fontproperties"] = {"weight": fontsize_weight, "size": fontsize_title} + if x is not None and y is not None: + args["bbox_to_anchor"] = (x, y) + + # Use default plt.legend if no dict_color provided + if dict_color is None: + plt.legend(handles=handles, labels=labels, **args) + return ax + + # Check if legend exists + if remove_legend: + if ax.get_legend() is not None and len(ax.get_legend().get_lines()) > 0: + ax.legend_.remove() + + # Adjust and check dict_colors and all arguments depending on it + list_cat = check_dict_colors(list_cat=list_cat, dict_color=dict_color, labels=labels) + marker = check_marker(marker=marker, list_cat=list_cat, lw=lw) + marker_linestyle = check_linestyle(marker_linestyle=marker_linestyle, list_cat=list_cat) + + # Generate legend items if not provided using dict_cat and list_cat + if not handles and dict_color and list_cat: + handles = [_create_marker(dict_color[cat], cat, marker[i], marker_size, lw, edgecolor, marker_linestyle[i]) + for i, cat in enumerate(list_cat)] + labels = list_cat if labels is None else labels # Create the legend - legend = ax.legend(handles=handles, labels=labels, bbox_to_anchor=(x, y), ncol=ncol, loc=loc, - labelspacing=labelspacing, columnspacing=columnspacing, borderpad=0, **args, title=title) + legend = ax.legend(handles=handles, labels=labels, **args) + # Align title if needed if title_align_left: legend._legend_box.align = "left" - return ax + + if return_handles: + return handles, labels if labels else list_cat + else: + return ax diff --git a/aaanalysis/utils.py b/aaanalysis/utils.py index 05a6b9bd..7731b4ce 100644 --- a/aaanalysis/utils.py +++ b/aaanalysis/utils.py @@ -11,6 +11,7 @@ from aaanalysis._utils._utils_check import (check_number_range, check_number_val, check_str, check_bool, check_dict, check_tuple, + check_ax, check_feat_matrix, check_col_in_df) from aaanalysis._utils._utils_output import (print_red, print_start_progress, print_progress, print_finished_progress) from aaanalysis._utils.utils_aaclust import (check_model, check_min_th, check_merge_metric, diff --git a/docs/build/doctrees/api.doctree b/docs/build/doctrees/api.doctree index 9320b6cd..125f5406 100644 Binary files a/docs/build/doctrees/api.doctree and b/docs/build/doctrees/api.doctree differ diff --git a/docs/build/doctrees/environment.pickle b/docs/build/doctrees/environment.pickle index e607e993..78a9dc89 100644 Binary files a/docs/build/doctrees/environment.pickle and b/docs/build/doctrees/environment.pickle differ diff --git a/docs/build/doctrees/generated/aaanalysis.CPPPlot.doctree b/docs/build/doctrees/generated/aaanalysis.CPPPlot.doctree index e7da3b0a..b6a6f4f6 100644 Binary files a/docs/build/doctrees/generated/aaanalysis.CPPPlot.doctree and b/docs/build/doctrees/generated/aaanalysis.CPPPlot.doctree differ diff --git a/docs/build/doctrees/generated/aaanalysis.plot_gcfs.doctree b/docs/build/doctrees/generated/aaanalysis.plot_gcfs.doctree index e307e16e..7d151547 100644 Binary files a/docs/build/doctrees/generated/aaanalysis.plot_gcfs.doctree and b/docs/build/doctrees/generated/aaanalysis.plot_gcfs.doctree differ diff --git a/docs/build/doctrees/generated/aaanalysis.plot_get_cdict.doctree b/docs/build/doctrees/generated/aaanalysis.plot_get_cdict.doctree index 87c6590d..f1b95ee3 100644 Binary files a/docs/build/doctrees/generated/aaanalysis.plot_get_cdict.doctree and b/docs/build/doctrees/generated/aaanalysis.plot_get_cdict.doctree differ diff --git a/docs/build/doctrees/generated/aaanalysis.plot_get_cmap.doctree b/docs/build/doctrees/generated/aaanalysis.plot_get_cmap.doctree index c9796c46..134e7773 100644 Binary files a/docs/build/doctrees/generated/aaanalysis.plot_get_cmap.doctree and b/docs/build/doctrees/generated/aaanalysis.plot_get_cmap.doctree differ diff --git a/docs/build/doctrees/generated/aaanalysis.plot_set_legend.doctree b/docs/build/doctrees/generated/aaanalysis.plot_set_legend.doctree index fb6d716c..4d3e3b74 100644 Binary files a/docs/build/doctrees/generated/aaanalysis.plot_set_legend.doctree and b/docs/build/doctrees/generated/aaanalysis.plot_set_legend.doctree differ diff --git a/docs/build/doctrees/generated/aaanalysis.plot_settings.doctree b/docs/build/doctrees/generated/aaanalysis.plot_settings.doctree index 64aed53f..0656d187 100644 Binary files a/docs/build/doctrees/generated/aaanalysis.plot_settings.doctree and b/docs/build/doctrees/generated/aaanalysis.plot_settings.doctree differ diff --git a/docs/build/doctrees/index/CONTRIBUTING_COPY.doctree b/docs/build/doctrees/index/CONTRIBUTING_COPY.doctree index 87914dfe..d05e403b 100644 Binary files a/docs/build/doctrees/index/CONTRIBUTING_COPY.doctree and b/docs/build/doctrees/index/CONTRIBUTING_COPY.doctree differ diff --git a/docs/build/html/_downloads/004048c0cbb6684bdb9047282ab71735/aaanalysis-plot_settings-2.pdf b/docs/build/html/_downloads/004048c0cbb6684bdb9047282ab71735/aaanalysis-plot_settings-2.pdf index 21496ef7..aeb2c207 100644 Binary files a/docs/build/html/_downloads/004048c0cbb6684bdb9047282ab71735/aaanalysis-plot_settings-2.pdf and b/docs/build/html/_downloads/004048c0cbb6684bdb9047282ab71735/aaanalysis-plot_settings-2.pdf differ diff --git a/docs/build/html/_downloads/07310bb7778e8d1b76ad8685f3fc0988/aaanalysis-plot_set_legend-1.py b/docs/build/html/_downloads/07310bb7778e8d1b76ad8685f3fc0988/aaanalysis-plot_set_legend-1.py new file mode 100644 index 00000000..8869506d --- /dev/null +++ b/docs/build/html/_downloads/07310bb7778e8d1b76ad8685f3fc0988/aaanalysis-plot_set_legend-1.py @@ -0,0 +1,12 @@ +import matplotlib.pyplot as plt +import seaborn as sns +import aaanalysis as aa +data = {'Classes': ['A', 'B', 'C'], 'Values': [23, 27, 43]} +colors = aa.plot_get_cmap(name="CAT", n_colors=3) +aa.plot_settings() +sns.barplot(x='Classes', y='Values', data=data, palette=colors) +sns.despine() +dict_color = dict(zip(["Class A", "Class B", "Class C"], colors)) +aa.plot_set_legend(dict_color=dict_color, marker="-", lw=10, loc_out=True) +plt.tight_layout() +plt.show() diff --git a/docs/build/html/_downloads/2a58656d4cb61bad4f791aca80114c58/aaanalysis-plot_settings-2.py b/docs/build/html/_downloads/2a58656d4cb61bad4f791aca80114c58/aaanalysis-plot_settings-2.py index 913cb0b4..3d0cf45c 100644 --- a/docs/build/html/_downloads/2a58656d4cb61bad4f791aca80114c58/aaanalysis-plot_settings-2.py +++ b/docs/build/html/_downloads/2a58656d4cb61bad4f791aca80114c58/aaanalysis-plot_settings-2.py @@ -1,8 +1,6 @@ import matplotlib.pyplot as plt import seaborn as sns import aaanalysis as aa -import aaanalysis.plotting.plot_get_cmap_ - data = {'Classes': ['Class A', 'Class B', 'Class C'], 'Values': [23, 27, 43]} colors = aa.plot_get_cmap(name="CAT", n_colors=3) aa.plot_settings() diff --git a/docs/build/html/_downloads/35bc22b1e83749ed4d42c9955ce176d6/aaanalysis-plot_set_legend-1.pdf b/docs/build/html/_downloads/35bc22b1e83749ed4d42c9955ce176d6/aaanalysis-plot_set_legend-1.pdf new file mode 100644 index 00000000..59a5ce68 Binary files /dev/null and b/docs/build/html/_downloads/35bc22b1e83749ed4d42c9955ce176d6/aaanalysis-plot_set_legend-1.pdf differ diff --git a/docs/build/html/_downloads/795a736e5af756908120c8bda412fd28/aaanalysis-plot_get_cmap-1.pdf b/docs/build/html/_downloads/795a736e5af756908120c8bda412fd28/aaanalysis-plot_get_cmap-1.pdf index 90805902..49c663bf 100644 Binary files a/docs/build/html/_downloads/795a736e5af756908120c8bda412fd28/aaanalysis-plot_get_cmap-1.pdf and b/docs/build/html/_downloads/795a736e5af756908120c8bda412fd28/aaanalysis-plot_get_cmap-1.pdf differ diff --git a/docs/build/html/_downloads/98288bbc4f2cb8e32adb4812b1b49e5e/aaanalysis-plot_set_legend-1.png b/docs/build/html/_downloads/98288bbc4f2cb8e32adb4812b1b49e5e/aaanalysis-plot_set_legend-1.png new file mode 100644 index 00000000..ef210743 Binary files /dev/null and b/docs/build/html/_downloads/98288bbc4f2cb8e32adb4812b1b49e5e/aaanalysis-plot_set_legend-1.png differ diff --git a/docs/build/html/_downloads/b89a5a5e2e370853db1a08a17e57d011/aaanalysis-plot_get_cmap-1.py b/docs/build/html/_downloads/b89a5a5e2e370853db1a08a17e57d011/aaanalysis-plot_get_cmap-1.py index c3454347..a7a0a0ad 100644 --- a/docs/build/html/_downloads/b89a5a5e2e370853db1a08a17e57d011/aaanalysis-plot_get_cmap-1.py +++ b/docs/build/html/_downloads/b89a5a5e2e370853db1a08a17e57d011/aaanalysis-plot_get_cmap-1.py @@ -1,8 +1,6 @@ import matplotlib.pyplot as plt import seaborn as sns import aaanalysis as aa -import aaanalysis.plotting.plot_get_cmap_ - colors = aa.plot_get_cmap(name="CAT", n_colors=4) data = {'Classes': ['Class A', 'Class B', 'Class C', "Class D"], 'Values': [23, 27, 43, 38]} aa.plot_settings(no_ticks_x=True, font_scale=1.2) diff --git a/docs/build/html/_downloads/ce02d0510516ba5d50e98b61882a2591/aaanalysis-plot_set_legend-1.hires.png b/docs/build/html/_downloads/ce02d0510516ba5d50e98b61882a2591/aaanalysis-plot_set_legend-1.hires.png new file mode 100644 index 00000000..db47c8df Binary files /dev/null and b/docs/build/html/_downloads/ce02d0510516ba5d50e98b61882a2591/aaanalysis-plot_set_legend-1.hires.png differ diff --git a/docs/build/html/_downloads/fb29bffb69140db4f68c4eb913c6f7d3/aaanalysis-plot_settings-1.pdf b/docs/build/html/_downloads/fb29bffb69140db4f68c4eb913c6f7d3/aaanalysis-plot_settings-1.pdf index 689c9fcd..d3b7eb18 100644 Binary files a/docs/build/html/_downloads/fb29bffb69140db4f68c4eb913c6f7d3/aaanalysis-plot_settings-1.pdf and b/docs/build/html/_downloads/fb29bffb69140db4f68c4eb913c6f7d3/aaanalysis-plot_settings-1.pdf differ diff --git a/docs/build/html/_images/aaanalysis-plot_set_legend-1.png b/docs/build/html/_images/aaanalysis-plot_set_legend-1.png new file mode 100644 index 00000000..ef210743 Binary files /dev/null and b/docs/build/html/_images/aaanalysis-plot_set_legend-1.png differ diff --git a/docs/build/html/_sources/index/CONTRIBUTING_COPY.rst.txt b/docs/build/html/_sources/index/CONTRIBUTING_COPY.rst.txt index 43ff2245..981b34d1 100644 --- a/docs/build/html/_sources/index/CONTRIBUTING_COPY.rst.txt +++ b/docs/build/html/_sources/index/CONTRIBUTING_COPY.rst.txt @@ -380,7 +380,7 @@ or a custom testing template: 1. Normal Cases Test Class: - Name: 'Test[TARGET FUNCTION NAME]'. - Objective: Test EACH parameter *INDIVIDUALLY*. - - Tests: For EACH parameter, at least 10 positive and 10 negative tests. + - Tests: Test EACH parameter, at least 10 positive and 10 negative tests for this class. 2. Complex Cases Test Class: - Name: 'Test[TARGET FUNCTION NAME]Complex'. diff --git a/docs/build/html/api.html b/docs/build/html/api.html index ed51cb52..8c2c6552 100644 --- a/docs/build/html/api.html +++ b/docs/build/html/api.html @@ -202,7 +202,7 @@

Plot Utilities

aaanalysis.plot_settings([font_scale, font, ...])

Configure general settings for plot visualization with various customization options.

-

aaanalysis.plot_set_legend([ax, handles, ...])

+

aaanalysis.plot_set_legend([ax, ...])

Set a customizable legend for a plot.

aaanalysis.plot_gcfs()

diff --git a/docs/build/html/generated/aaanalysis.CPPPlot.html b/docs/build/html/generated/aaanalysis.CPPPlot.html index 122bfd0c..80db38b1 100644 --- a/docs/build/html/generated/aaanalysis.CPPPlot.html +++ b/docs/build/html/generated/aaanalysis.CPPPlot.html @@ -128,7 +128,7 @@

aaanalysis.CPPPlot

-class aaanalysis.CPPPlot(df_cat=None, accept_gaps=False, jmd_n_len=10, jmd_c_len=10, ext_len=4, verbose=True)[source]
+class aaanalysis.CPPPlot(df_cat=None, accept_gaps=False, jmd_n_len=10, jmd_c_len=10, ext_len=4, verbose=True)[source]

Bases: object

Create and filter features that are most discriminant between two sets of sequences.

@@ -145,7 +145,7 @@

aaanalysis.CPPPlot
-__init__(df_cat=None, accept_gaps=False, jmd_n_len=10, jmd_c_len=10, ext_len=4, verbose=True)[source]
+__init__(df_cat=None, accept_gaps=False, jmd_n_len=10, jmd_c_len=10, ext_len=4, verbose=True)[source]

Methods

@@ -167,7 +167,7 @@

aaanalysis.CPPPlot
-profile(df_feat=None, y='category', val_col='mean_dif', val_type='count', normalize=False, figsize=(7, 5), title=None, title_kws=None, dict_color=None, edge_color='none', bar_width=0.75, add_jmd_tmd=True, tmd_len=20, start=1, jmd_n_seq=None, tmd_seq=None, jmd_c_seq=None, tmd_color='mediumspringgreen', jmd_color='blue', tmd_seq_color='black', jmd_seq_color='white', seq_size=None, tmd_jmd_fontsize=None, xtick_size=11.0, xtick_width=2.0, xtick_length=5.0, xticks_pos=False, ytick_size=None, ytick_width=2.0, ytick_length=5.0, ylim=None, highlight_tmd_area=True, highlight_alpha=0.15, grid=False, grid_axis='both', add_legend_cat=True, legend_kws=None, shap_plot=False, **kwargs)[source]
+profile(df_feat=None, y='category', val_col='mean_dif', val_type='count', normalize=False, figsize=(7, 5), title=None, title_kws=None, dict_color=None, edge_color='none', bar_width=0.75, add_jmd_tmd=True, tmd_len=20, start=1, jmd_n_seq=None, tmd_seq=None, jmd_c_seq=None, tmd_color='mediumspringgreen', jmd_color='blue', tmd_seq_color='black', jmd_seq_color='white', seq_size=None, tmd_jmd_fontsize=None, xtick_size=11.0, xtick_width=2.0, xtick_length=5.0, xticks_pos=False, ytick_size=None, ytick_width=2.0, ytick_length=5.0, ylim=None, highlight_tmd_area=True, highlight_alpha=0.15, grid=False, grid_axis='both', add_legend_cat=True, legend_kws=None, shap_plot=False, **kwargs)[source]

Plot feature profile for given features from ‘df_feat’.

Parameters:
@@ -224,7 +224,7 @@

aaanalysis.CPPPlot
-heatmap(df_feat=None, y='subcategory', val_col='mean_dif', val_type='mean', normalize=False, figsize=(8, 5), title=None, title_kws=None, vmin=None, vmax=None, grid_on=True, cmap='RdBu_r', cmap_n_colors=None, dict_color=None, cbar_kws=None, facecolor_dark=False, add_jmd_tmd=True, tmd_len=20, start=1, jmd_n_seq=None, tmd_seq=None, jmd_c_seq=None, tmd_color='mediumspringgreen', jmd_color='blue', tmd_seq_color='black', jmd_seq_color='white', seq_size=None, tmd_jmd_fontsize=None, xticks_pos=False, xtick_size=11.0, xtick_width=2.0, xtick_length=5.0, ytick_size=None, add_legend_cat=True, legend_kws=None, add_importance_map=False, cbar_pct=False, **kwargs)[source]
+heatmap(df_feat=None, y='subcategory', val_col='mean_dif', val_type='mean', normalize=False, figsize=(8, 5), title=None, title_kws=None, vmin=None, vmax=None, grid_on=True, cmap='RdBu_r', cmap_n_colors=None, dict_color=None, cbar_kws=None, facecolor_dark=False, add_jmd_tmd=True, tmd_len=20, start=1, jmd_n_seq=None, tmd_seq=None, jmd_c_seq=None, tmd_color='mediumspringgreen', jmd_color='blue', tmd_seq_color='black', jmd_seq_color='white', seq_size=None, tmd_jmd_fontsize=None, xticks_pos=False, xtick_size=11.0, xtick_width=2.0, xtick_length=5.0, ytick_size=None, add_legend_cat=True, legend_kws=None, add_importance_map=False, cbar_pct=False, **kwargs)[source]

Plot a featuremap of the selected value column with scale information (y-axis) versus sequence position (x-axis).

This is a wrapper function for seaborn.heatmap(), designed to highlight differences between two sets of sequences at the positional level (e.g., amino acid level for protein sequences).

@@ -309,7 +309,7 @@

aaanalysis.CPPPlot
-update_seq_size()[source]
+update_seq_size()[source]

diff --git a/docs/build/html/generated/aaanalysis.plot_gcfs.html b/docs/build/html/generated/aaanalysis.plot_gcfs.html index a499808b..6d9fede2 100644 --- a/docs/build/html/generated/aaanalysis.plot_gcfs.html +++ b/docs/build/html/generated/aaanalysis.plot_gcfs.html @@ -129,7 +129,7 @@

aaanalysis.plot_gcfs

-aaanalysis.plot_gcfs()[source]
+aaanalysis.plot_gcfs()[source]

Get current font size, which is set by plot_settings() function.

diff --git a/docs/build/html/generated/aaanalysis.plot_get_cdict.html b/docs/build/html/generated/aaanalysis.plot_get_cdict.html index c601fe6b..ffb2ed4b 100644 --- a/docs/build/html/generated/aaanalysis.plot_get_cdict.html +++ b/docs/build/html/generated/aaanalysis.plot_get_cdict.html @@ -129,7 +129,7 @@

aaanalysis.plot_get_cdict

-aaanalysis.plot_get_cdict(name='DICT_COLOR')[source]
+aaanalysis.plot_get_cdict(name='DICT_COLOR')[source]

Returns color dictionaries specified for AAanalysis.

Parameters:
diff --git a/docs/build/html/generated/aaanalysis.plot_get_cmap.html b/docs/build/html/generated/aaanalysis.plot_get_cmap.html index 0d6f092e..7706f738 100644 --- a/docs/build/html/generated/aaanalysis.plot_get_cmap.html +++ b/docs/build/html/generated/aaanalysis.plot_get_cmap.html @@ -129,7 +129,7 @@

aaanalysis.plot_get_cmap

-aaanalysis.plot_get_cmap(name='CPP', n_colors=101, facecolor_dark=False)[source]
+aaanalysis.plot_get_cmap(name='CPP', n_colors=101, facecolor_dark=False)[source]

Returns color maps specified for AAanalysis.

Parameters:
diff --git a/docs/build/html/generated/aaanalysis.plot_set_legend.html b/docs/build/html/generated/aaanalysis.plot_set_legend.html index c53a29d3..6a4570c3 100644 --- a/docs/build/html/generated/aaanalysis.plot_set_legend.html +++ b/docs/build/html/generated/aaanalysis.plot_set_legend.html @@ -129,36 +129,45 @@

aaanalysis.plot_set_legend

-aaanalysis.plot_set_legend(ax=None, handles=None, dict_color=None, list_cat=None, labels=None, y=None, x=None, ncol=3, fontsize=None, weight='normal', lw=0, edgecolor=None, return_handles=False, loc='upper left', labelspacing=0.2, columnspacing=1, title=None, fontsize_legend=None, title_align_left=True, fontsize_weight='normal', shape=None, **kwargs)[source]
+aaanalysis.plot_set_legend(ax=None, remove_legend=True, handles=None, return_handles=False, dict_color=None, list_cat=None, labels=None, loc='upper left', loc_out=False, y=None, x=None, ncol=3, labelspacing=0.2, columnspacing=1.0, handletextpad=0.8, handlelength=2, fontsize=None, fontsize_title=None, weight='normal', fontsize_weight='normal', lw=0, edgecolor=None, marker=None, marker_size=10, marker_linestyle='-', title=None, title_align_left=True, **kwargs)[source]

Set a customizable legend for a plot.

+

Legends can be flexbily adjusted based on handles or categories and colors provided in dict_color. +This functions comprises the most convinient settings for func:`matplotlib.pyplot.legend.

Parameters:
  • ax (Optional[Axes]) – The axes to attach the legend to. If not provided, the current axes will be used.

  • -
  • handles (Optional[List]) – Handles for legend items. If not provided, they will be generated based on dict_color and list_cat.

  • +
  • remove_legend (bool) – Remove legend of given or current axes.

  • +
  • handles (Optional[List]) – Handles for legend items. If not provided, they will be generated based on dict_color and list_cat.

  • +
  • return_handles (bool) – Whether to return handles and labels. If True, function returns handles, labels instead of the axes.

  • dict_color (Optional[Dict[str, str]]) – A dictionary mapping categories to colors.

  • -
  • list_cat (Optional[List[str]]) – List of categories to include in the legend.

  • -
  • labels (Optional[List[str]]) – Labels for legend items.

  • -
  • y (Optional[int]) – The y-coordinate for the legend’s anchor point.

  • -
  • x (Optional[int]) – The x-coordinate for the legend’s anchor point.

  • +
  • list_cat (Optional[List[str]]) – List of categories to include in the legend (keys of dict_color).

  • +
  • labels (Optional[List[str]]) – Labels for legend items corresponding to given categories.

  • +
  • loc (str) – Location for the legend.

  • +
  • loc_out (bool) – If True, sets automatically x=0 and y=-0.25 if they are None.

  • +
  • y (Union[int, float, None]) – The y-coordinate for the legend’s anchor point.

  • +
  • x (Union[int, float, None]) – The x-coordinate for the legend’s anchor point.

  • ncol (int) – Number of columns in the legend.

  • -
  • fontsize (Optional[int]) – Font size for the legend text.

  • +
  • labelspacing (Union[int, float]) – Vertical spacing between legend items.

  • +
  • columnspacing (Union[int, float]) – Horizontal spacing between legend columns.

  • +
  • handletextpad (Union[int, float]) – Horizontal spacing bewtween legend handle (marker) and label.

  • +
  • handlelength (Union[int, float]) – Length of legend handle (marker).

  • +
  • fontsize (Union[int, float, None]) – Font size for the legend text.

  • +
  • fontsize_title (Union[int, float, None]) – Font size for the legend title.

  • weight (str) – Weight of the font.

  • -
  • lw (float) – Line width for legend items.

  • +
  • fontsize_weight (str) – Font weight for the legend title.

  • +
  • lw (Union[int, float]) – Line width for legend items.

  • edgecolor (Optional[str]) – Edge color for legend items.

  • -
  • return_handles (bool) – Whether to return handles and labels. If True, function returns handles, labels instead of the axes.

  • -
  • loc (str) – Location for the legend.

  • -
  • labelspacing (float) – Vertical spacing between legend items.

  • -
  • columnspacing (int) – Horizontal spacing between legend columns.

  • +
  • marker (Union[str, int, list, None]) – Marker shape for legend items. ‘-’ is added to the matplotlib default options to use lines as markers.

  • +
  • marker_size (Union[int, float]) – Marker size for legend items.

  • +
  • marker_linestyle (Union[str, list]) – Marker linestyle of legend items.

  • title (Optional[str]) – Title for the legend.

  • -
  • fontsize_legend (Optional[int]) – Font size for the legend title.

  • title_align_left (bool) – Whether to align the title to the left.

  • -
  • fontsize_weight (str) – Font weight for the legend title.

  • -
  • shape (Optional[str]) – Marker shape for legend items. Refer to matplotlib.lines.Line2D for available shapes.

  • +
  • **kwargs – Furhter key word arguments for matplotlib.axes.Axes.legend().

Returns:
-

The axes with the legend applied. If return_handles=True, it returns handles and labels instead.

+

The axes with the legend applied. If return_handles=True, it returns handles and labels instead.

Return type:

ax

@@ -166,19 +175,34 @@

aaanalysis.plot_set_legend

Examples

-

See also

-
-
matplotlib.pyplot.legend

For additional details on how the ‘loc’ parameter can be customized.

-
-
matplotlib.lines.Line2D

For details on the different types of marker shapes (‘shape’ parameter).

-
-
+
    +
  • Matplotlib markers <https://matplotlib.org/stable/api/markers_api.html>.

  • +
  • Linestyles of markers <https://matplotlib.org/stable/gallery/lines_bars_and_markers/linestyles.html>

  • +
  • matplotlib.lines.Line2D() for available marker shapes and line properties.

  • +
  • matplotlib.axes.Axes(), which is the core object in matplotlib.

  • +
  • matplotlib.pyplot.gca() to get the current Axes instance.

  • +

diff --git a/docs/build/html/generated/aaanalysis.plot_settings.html b/docs/build/html/generated/aaanalysis.plot_settings.html index e2418fe0..0cc61734 100644 --- a/docs/build/html/generated/aaanalysis.plot_settings.html +++ b/docs/build/html/generated/aaanalysis.plot_settings.html @@ -129,7 +129,7 @@

aaanalysis.plot_settings

-aaanalysis.plot_settings(font_scale=1, font='Arial', fig_format='pdf', weight_bold=True, adjust_only_font=False, adjust_further_elements=True, grid=False, grid_axis='y', no_ticks=False, short_ticks=False, no_ticks_x=False, short_ticks_x=False, no_ticks_y=False, short_ticks_y=False, show_options=False)[source]
+aaanalysis.plot_settings(font_scale=1, font='Arial', fig_format='pdf', weight_bold=True, adjust_only_font=False, adjust_further_elements=True, grid=False, grid_axis='y', no_ticks=False, short_ticks=False, no_ticks_x=False, short_ticks_x=False, no_ticks_y=False, short_ticks_y=False, show_options=False)[source]

Configure general settings for plot visualization with various customization options.

This function modifies the global settings of matplotlib and seaborn libraries. PDFs are embedded such that they can be edited using image editing software.

diff --git a/docs/build/html/index/CONTRIBUTING_COPY.html b/docs/build/html/index/CONTRIBUTING_COPY.html index 8f5171fb..b6711419 100644 --- a/docs/build/html/index/CONTRIBUTING_COPY.html +++ b/docs/build/html/index/CONTRIBUTING_COPY.html @@ -489,7 +489,7 @@

Testing