# Path: onecodex/lib/enums.py
# class AlphaDiversityMetric(BaseEnum):
#     Simpson = "simpson"
#     ObservedTaxa = "observed_taxa"
#     Shannon = "shannon"
#     Chao1 = "chao1"
# 
# class Rank(BaseEnum):
#     """Python does not allow extending enums so we have to repeat the ranks."""
# 
#     Superkingdom = "superkingdom"
#     Kingdom = "kingdom"
#     Phylum = "phylum"
#     Class = "class"
#     Order = "order"
#     Family = "family"
#     Genus = "genus"
#     Species = "species"
#     Auto = "auto"
# 
# class BaseEnum(str, Enum):
#     @classmethod
#     def has_value(cls, value):
#         return value in cls.values()
# 
#     @classmethod
#     def values(cls):
#         return [e.value for e in cls]
# 
# Path: onecodex/exceptions.py
# class OneCodexException(Exception):
#     pass
# 
# class PlottingException(OneCodexException):
#     """User-facing plotting error for cases when the user may take action to resolve the issue."""
# 
#     pass
# 
# class PlottingWarning(UserWarning):
#     """User-facing plotting warning for cases when the user may take action to resolve the issue."""
# 
#     pass
# 
# Path: onecodex/viz/_primitives.py
# def prepare_props(title=None, height=None, width=None):
#     """Prepare key plotting kwargs for passing to Altair, which d/n like None values."""
#     props = {}
#     if title:
#         props["title"] = title  # None gets rendered as `None`
#     if height:
#         props["height"] = height  # None violates Vega JSON Schema
#     if width:
#         props["width"] = width  # None violates Vega JSON Schema
#     return props
# 
# def sort_helper(sort, values):
#     """Return a sorted list of values for the Altair chart axes."""
#     sort_order = None
# 
#     if callable(sort):
#         values = list(set(values))
#         sort_order = sort(values)
#     elif isinstance(sort, list):
#         if set(sort) != set(values):
#             raise OneCodexException("sort_x must have the same items as your dataset.")
#         sort_order = sort
#     elif sort:
#         raise OneCodexException(
#             "Please pass either a sorted list of values matching the axis labels \
#             or a function that returns a sorted list of labels"
#         )
# 
#     return sort_order
# 
# def get_base_classification_url():
#     return os.environ.get("ONE_CODEX_API_BASE", "https://app.onecodex.com") + "/classification/"


import warnings
        import altair as alt
        import pandas as pd
from onecodex.lib.enums import AlphaDiversityMetric, Rank, BaseEnum
from onecodex.exceptions import OneCodexException, PlottingException, PlottingWarning
from onecodex.viz._primitives import prepare_props, sort_helper, get_base_classification_url
        if not PlotType.has_value(plot_type):
            raise OneCodexException("Plot type must be one of: auto, boxplot, scatter")

        if len(self._results) < 1:
            raise PlottingException(
                "There are too few samples for metadata plots after filtering. Please select 1 or "
                "more samples to plot."
            )

        # alpha diversity is only allowed on vertical axis--horizontal can be magically mapped
        metadata_fields = [haxis, "Label"]
        if facet_by:
            metadata_fields.append(facet_by)
        df, magic_fields = self._metadata_fetch(metadata_fields, label=label)

        if AlphaDiversityMetric.has_value(vaxis):
            df.loc[:, vaxis] = self.alpha_diversity(vaxis, rank=rank)
            magic_fields[vaxis] = vaxis
            df.dropna(subset=[magic_fields[vaxis]], inplace=True)
        else:
            # if it's not alpha diversity, vertical axis can also be magically mapped
            vert_df, vert_magic_fields = self._metadata_fetch([vaxis])

            # we require the vertical axis to be numerical otherwise plots get weird
            if (
                pd.api.types.is_bool_dtype(vert_df[vert_magic_fields[vaxis]])
                or pd.api.types.is_categorical_dtype(vert_df[vert_magic_fields[vaxis]])
                or pd.api.types.is_object_dtype(vert_df[vert_magic_fields[vaxis]])
                or not pd.api.types.is_numeric_dtype(vert_df[vert_magic_fields[vaxis]])
            ):  # noqa

# Path: onecodex/lib/enums.py
# class AlphaDiversityMetric(BaseEnum):
#     Simpson = "simpson"
#     ObservedTaxa = "observed_taxa"
#     Shannon = "shannon"
#     Chao1 = "chao1"
# 
# class Rank(BaseEnum):
#     """Python does not allow extending enums so we have to repeat the ranks."""
# 
#     Superkingdom = "superkingdom"
#     Kingdom = "kingdom"
#     Phylum = "phylum"
#     Class = "class"
#     Order = "order"
#     Family = "family"
#     Genus = "genus"
#     Species = "species"
#     Auto = "auto"
# 
# class BaseEnum(str, Enum):
#     @classmethod
#     def has_value(cls, value):
#         return value in cls.values()
# 
#     @classmethod
#     def values(cls):
#         return [e.value for e in cls]
# 
# Path: onecodex/exceptions.py
# class OneCodexException(Exception):
#     pass
# 
# class PlottingException(OneCodexException):
#     """User-facing plotting error for cases when the user may take action to resolve the issue."""
# 
#     pass
# 
# class PlottingWarning(UserWarning):
#     """User-facing plotting warning for cases when the user may take action to resolve the issue."""
# 
#     pass
# 
# Path: onecodex/viz/_primitives.py
# def prepare_props(title=None, height=None, width=None):
#     """Prepare key plotting kwargs for passing to Altair, which d/n like None values."""
#     props = {}
#     if title:
#         props["title"] = title  # None gets rendered as `None`
#     if height:
#         props["height"] = height  # None violates Vega JSON Schema
#     if width:
#         props["width"] = width  # None violates Vega JSON Schema
#     return props
# 
# def sort_helper(sort, values):
#     """Return a sorted list of values for the Altair chart axes."""
#     sort_order = None
# 
#     if callable(sort):
#         values = list(set(values))
#         sort_order = sort(values)
#     elif isinstance(sort, list):
#         if set(sort) != set(values):
#             raise OneCodexException("sort_x must have the same items as your dataset.")
#         sort_order = sort
#     elif sort:
#         raise OneCodexException(
#             "Please pass either a sorted list of values matching the axis labels \
#             or a function that returns a sorted list of labels"
#         )
# 
#     return sort_order
# 
# def get_base_classification_url():
#     return os.environ.get("ONE_CODEX_API_BASE", "https://app.onecodex.com") + "/classification/"


# Path: onecodex/viz/_metadata.py
import warnings
        import altair as alt
        import pandas as pd
from onecodex.lib.enums import AlphaDiversityMetric, Rank, BaseEnum
from onecodex.exceptions import OneCodexException, PlottingException, PlottingWarning
from onecodex.viz._primitives import prepare_props, sort_helper, get_base_classification_url

        if not PlotType.has_value(plot_type):
            raise OneCodexException("Plot type must be one of: auto, boxplot, scatter")

        if len(self._results) < 1:
            raise PlottingException(
                "There are too few samples for metadata plots after filtering. Please select 1 or "
                "more samples to plot."
            )

        # alpha diversity is only allowed on vertical axis--horizontal can be magically mapped
        metadata_fields = [haxis, "Label"]
        if facet_by:
            metadata_fields.append(facet_by)
        df, magic_fields = self._metadata_fetch(metadata_fields, label=label)

        if AlphaDiversityMetric.has_value(vaxis):
            df.loc[:, vaxis] = self.alpha_diversity(vaxis, rank=rank)
            magic_fields[vaxis] = vaxis
            df.dropna(subset=[magic_fields[vaxis]], inplace=True)
        else:
            # if it's not alpha diversity, vertical axis can also be magically mapped
            vert_df, vert_magic_fields = self._metadata_fetch([vaxis])

            # we require the vertical axis to be numerical otherwise plots get weird
            if (
                pd.api.types.is_bool_dtype(vert_df[vert_magic_fields[vaxis]])
                or pd.api.types.is_categorical_dtype(vert_df[vert_magic_fields[vaxis]])
                or pd.api.types.is_object_dtype(vert_df[vert_magic_fields[vaxis]])
                or not pd.api.types.is_numeric_dtype(vert_df[vert_magic_fields[vaxis]])
            ):  # noqa

                raise OneCodexException("Metadata field on vertical axis must be numerical")