# Path: metatlas/datastructures/id_types.py
# OUTPUT_TYPES = [
#     OutputType("ISTDsEtc"),
#     OutputType("FinalEMA-HILIC"),
#     OutputType("FinalEMA-C18"),
#     OutputType("data_QC"),
#     OutputType("other"),
# ]
# POLARITIES = [Polarity("positive"), Polarity("negative"), Polarity("fast-polarity-switching")]
# SHORT_POLARITIES = {
#     Polarity("positive"): ShortPolarity("POS"),
#     Polarity("negative"): ShortPolarity("NEG"),
#     Polarity("fast-polarity-switching"): ShortPolarity("FPS"),
# }
# class Proposal(TypedDict):
# class LcmsRunDict(TypedDict):
# 
# Path: metatlas/datastructures/utils.py
# def get_atlas(name: AtlasName, username: Username) -> metob.Atlas:
# 
# Path: metatlas/io/write_utils.py
# def make_dir_for(file_path):
# def check_existing_file(file_path, overwrite=False):
# def export_dataframe(dataframe, file_path, description, overwrite=False, **kwargs):
# def raise_on_diff(dataframe, file_path, description, **kwargs):
# def export_dataframe_die_on_diff(dataframe, file_path, description, overwrite=False, **kwargs):
# 
# Path: metatlas/tools/util.py
# def or_default(none_or_value, default):
#     """
#     inputs:
#         none_or_value: variable to test
#         default: value to return if none_or_value is None
#     """
#     return none_or_value if none_or_value is not None else default


import getpass
import logging
import os
import pandas as pd
import traitlets
import metatlas.datastructures.metatlas_objects as metob
import metatlas.plots.dill2plots as dp
from typing import cast, Dict, List, Optional
from traitlets import Bool, TraitError, observe, validate
from traitlets import HasTraits, Int, Unicode
from traitlets.traitlets import ObserveHandler
from metatlas.datastructures.id_types import (
    AnalysisNumber,
    Experiment,
    FileMatchList,
    GroupList,
    GroupMatchList,
    LcmsRunDict,
    LcmsRunsList,
    PathString,
    Polarity,
    POLARITIES,
    Proposal,
    OutputType,
    OUTPUT_TYPES,
    ShortPolarity,
    SHORT_POLARITIES,
)
from metatlas.datastructures.utils import AtlasName, get_atlas, Username
from metatlas.io import write_utils
from metatlas.tools.util import or_default
        return append_inverse(out, polarity)

    @property
    def _default_exclude_groups(self) -> GroupMatchList:
        return self._get_default_exclude_groups(self.polarity)

    @validate("polarity")
    def _valid_polarity(self, proposal: Proposal) -> Polarity:
        if proposal["value"] not in POLARITIES:
            raise TraitError(f"Parameter polarity must be one of {', '.join(POLARITIES)}")
        return cast(Polarity, proposal["value"])

    @validate("output_type")
    def _valid_output_type(self, proposal: Proposal) -> OutputType:
        if proposal["value"] not in OUTPUT_TYPES:
            raise TraitError(f"Parameter output_type must be one of {', '.join(OUTPUT_TYPES)}")
        return cast(OutputType, proposal["value"])

    @validate("source_atlas")
    def _valid_source_atlas(self, proposal: Proposal) -> Optional[AtlasName]:
        if proposal["value"] is not None:
            proposed_name = cast(AtlasName, proposal["value"])
            try:
                get_atlas(proposed_name, cast(Username, "*"))  # raises error if not found or matches multiple
            except ValueError as err:
                raise TraitError(str(err)) from err
            return proposed_name
        return None

    @validate("analysis_number")

# Path: metatlas/datastructures/id_types.py
# OUTPUT_TYPES = [
#     OutputType("ISTDsEtc"),
#     OutputType("FinalEMA-HILIC"),
#     OutputType("FinalEMA-C18"),
#     OutputType("data_QC"),
#     OutputType("other"),
# ]
# POLARITIES = [Polarity("positive"), Polarity("negative"), Polarity("fast-polarity-switching")]
# SHORT_POLARITIES = {
#     Polarity("positive"): ShortPolarity("POS"),
#     Polarity("negative"): ShortPolarity("NEG"),
#     Polarity("fast-polarity-switching"): ShortPolarity("FPS"),
# }
# class Proposal(TypedDict):
# class LcmsRunDict(TypedDict):
# 
# Path: metatlas/datastructures/utils.py
# def get_atlas(name: AtlasName, username: Username) -> metob.Atlas:
# 
# Path: metatlas/io/write_utils.py
# def make_dir_for(file_path):
# def check_existing_file(file_path, overwrite=False):
# def export_dataframe(dataframe, file_path, description, overwrite=False, **kwargs):
# def raise_on_diff(dataframe, file_path, description, **kwargs):
# def export_dataframe_die_on_diff(dataframe, file_path, description, overwrite=False, **kwargs):
# 
# Path: metatlas/tools/util.py
# def or_default(none_or_value, default):
#     """
#     inputs:
#         none_or_value: variable to test
#         default: value to return if none_or_value is None
#     """
#     return none_or_value if none_or_value is not None else default


# Path: metatlas/datastructures/analysis_identifiers.py
import getpass
import logging
import os
import pandas as pd
import traitlets
import metatlas.datastructures.metatlas_objects as metob
import metatlas.plots.dill2plots as dp
from typing import cast, Dict, List, Optional
from traitlets import Bool, TraitError, observe, validate
from traitlets import HasTraits, Int, Unicode
from traitlets.traitlets import ObserveHandler
from metatlas.datastructures.id_types import (
    AnalysisNumber,
    Experiment,
    FileMatchList,
    GroupList,
    GroupMatchList,
    LcmsRunDict,
    LcmsRunsList,
    PathString,
    Polarity,
    POLARITIES,
    Proposal,
    OutputType,
    OUTPUT_TYPES,
    ShortPolarity,
    SHORT_POLARITIES,
)
from metatlas.datastructures.utils import AtlasName, get_atlas, Username
from metatlas.io import write_utils
from metatlas.tools.util import or_default

        return append_inverse(out, polarity)

    @property
    def _default_exclude_groups(self) -> GroupMatchList:
        return self._get_default_exclude_groups(self.polarity)

    @validate("polarity")
    def _valid_polarity(self, proposal: Proposal) -> Polarity:
        if proposal["value"] not in POLARITIES:
            raise TraitError(f"Parameter polarity must be one of {', '.join(POLARITIES)}")
        return cast(Polarity, proposal["value"])

    @validate("output_type")
    def _valid_output_type(self, proposal: Proposal) -> OutputType:
        if proposal["value"] not in OUTPUT_TYPES:
            raise TraitError(f"Parameter output_type must be one of {', '.join(OUTPUT_TYPES)}")
        return cast(OutputType, proposal["value"])

    @validate("source_atlas")
    def _valid_source_atlas(self, proposal: Proposal) -> Optional[AtlasName]:
        if proposal["value"] is not None:
            proposed_name = cast(AtlasName, proposal["value"])
            try:
                get_atlas(proposed_name, cast(Username, "*"))  # raises error if not found or matches multiple
            except ValueError as err:
                raise TraitError(str(err)) from err
            return proposed_name
        return None

    @validate("analysis_number")

    def _valid_analysis_number(self, proposal: Proposal) -> AnalysisNumber: