# Path: metatlas/datastructures/metatlas_objects.py
# FETCH_STUBS = True
# ADDUCTS = ('','[M]+','[M+H]+','[M+H]2+','[M+2H]2+','[M+H-H2O]2+','[M+K]2+','[M+NH4]+','[M+Na]+','[M+H-H2O]+','[M-H]-','[M-2H]-','[M-H+Cl]-','[M-2H]2-','[M+Cl]-','[2M+H]+','[2M-H]-','[M-H+Na]+','[M+K]+','[M+2Na]2+','[M-e]+','[M+acetate]-','[M+formate]-','[M-H+Cl]2-','[M-H+2Na]+')
# POLARITY = ('positive', 'negative', 'alternating')
# FRAGMENTATION_TECHNIQUE = ('hcd','cid','etd','ecd','irmpd')
# ID_GRADES: Dict[str, IdentificationGrade] = dict()
#     FETCH_STUBS = False
#         FETCH_STUBS = True
#     FETCH_STUBS = True
# def retrieve(object_type, **kwargs):
# def remove(object_type, **kwargs):
# def remove_objects(objects, all_versions=True, **kwargs):
# def store(objects, **kwargs):
#     def __init__(self, **kwargs):
#     def _update(self, override_user=False):
#     def clone(self, recursive=False):
#     def show_diff(self, unique_id=None):
#     def _on_update(self, change):
#     def __str__(self):
#     def __repr__(self):
#     def __getattribute__(self, name):
#     def validate(self, obj, value):
# def find_invalid_runs(**kwargs):
# def to_dataframe(objects):
# class MetatlasObject(HasTraits):
# class Method(MetatlasObject):
# class Sample(MetatlasObject):
# class LcmsRun(MetatlasObject):
# class FunctionalSet(MetatlasObject):
# class Compound(MetatlasObject):
# class Reference(MetatlasObject):
# class IdentificationGrade(MetatlasObject):
# class _IdGradeTrait(MetInstance):
# class Group(MetatlasObject):
# class MzIntensityPair(MetatlasObject):
# class FragmentationReference(Reference):
# class RtReference(Reference):
# class MzReference(Reference):
# class IntensityReference(Reference):
# class CompoundIdentification(MetatlasObject):
# class Atlas(MetatlasObject):
# class MZMineTask(MetatlasObject):
# 
# Path: metatlas/io/h5_query.py
# def get_data(h5file, **kwargs):
# def get_chromatogram(h5file, min_mz, max_mz, aggregator=np.sum, **kwargs):
# def get_heatmap(h5file, mz_bins, **kwargs):
# def get_spectrogram(h5file, min_rt, max_rt, bins=2000, **kwargs):
# def get_info(h5file):
# 
# 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):


import copy
import logging
import math
import os.path
import re
import sys
import dill
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import six
import tables
from collections import defaultdict
from textwrap import wrap
from metatlas.datastructures import metatlas_objects as metob
from metatlas.io import h5_query as h5q
from metatlas.io import write_utils
    second member to the tuple, which will not be used, such as ('attribute_name', 'as attribute')
    """
    if len(ids) == 0:
        raise ValueError('ids cannot be empty')
    if len(ids) == 1:
        if isinstance(ids[0], tuple):
            setattr(data, ids[0][0], value)
        elif isinstance(ids[0], str) and hasattr(data, ids[0]):
            setattr(data, ids[0], value)
        else:
            data[ids[0]] = value  # works for list or dict
    else:
        if isinstance(ids[0], tuple):
            set_nested(getattr(data, ids[0][0]), ids[1:], value)
        elif isinstance(ids[0], str) and hasattr(data, ids[0]):
            set_nested(getattr(data, ids[0]), ids[1:], value)
        else:
            set_nested(data[ids[0]], ids[1:], value)


def make_atlas_df(atlas):
    """
    inputs:
        atlas: metatlas.datastructures.metatlas_objects.Atlas
    output:
        pandas DataFrame with one row per CompoundIdentification in atlas and each row also includes
        the first RtReference, MzReference, and Compound from the CompoundIdentification
    """
    mzs = [extract(aci, ['mz_references', 0], metob.MzReference()) for aci in atlas.compound_identifications]
    rts = [extract(aci, ['rt_references', 0], metob.RtReference()) for aci in atlas.compound_identifications]

# Path: metatlas/datastructures/metatlas_objects.py
# FETCH_STUBS = True
# ADDUCTS = ('','[M]+','[M+H]+','[M+H]2+','[M+2H]2+','[M+H-H2O]2+','[M+K]2+','[M+NH4]+','[M+Na]+','[M+H-H2O]+','[M-H]-','[M-2H]-','[M-H+Cl]-','[M-2H]2-','[M+Cl]-','[2M+H]+','[2M-H]-','[M-H+Na]+','[M+K]+','[M+2Na]2+','[M-e]+','[M+acetate]-','[M+formate]-','[M-H+Cl]2-','[M-H+2Na]+')
# POLARITY = ('positive', 'negative', 'alternating')
# FRAGMENTATION_TECHNIQUE = ('hcd','cid','etd','ecd','irmpd')
# ID_GRADES: Dict[str, IdentificationGrade] = dict()
#     FETCH_STUBS = False
#         FETCH_STUBS = True
#     FETCH_STUBS = True
# def retrieve(object_type, **kwargs):
# def remove(object_type, **kwargs):
# def remove_objects(objects, all_versions=True, **kwargs):
# def store(objects, **kwargs):
#     def __init__(self, **kwargs):
#     def _update(self, override_user=False):
#     def clone(self, recursive=False):
#     def show_diff(self, unique_id=None):
#     def _on_update(self, change):
#     def __str__(self):
#     def __repr__(self):
#     def __getattribute__(self, name):
#     def validate(self, obj, value):
# def find_invalid_runs(**kwargs):
# def to_dataframe(objects):
# class MetatlasObject(HasTraits):
# class Method(MetatlasObject):
# class Sample(MetatlasObject):
# class LcmsRun(MetatlasObject):
# class FunctionalSet(MetatlasObject):
# class Compound(MetatlasObject):
# class Reference(MetatlasObject):
# class IdentificationGrade(MetatlasObject):
# class _IdGradeTrait(MetInstance):
# class Group(MetatlasObject):
# class MzIntensityPair(MetatlasObject):
# class FragmentationReference(Reference):
# class RtReference(Reference):
# class MzReference(Reference):
# class IntensityReference(Reference):
# class CompoundIdentification(MetatlasObject):
# class Atlas(MetatlasObject):
# class MZMineTask(MetatlasObject):
# 
# Path: metatlas/io/h5_query.py
# def get_data(h5file, **kwargs):
# def get_chromatogram(h5file, min_mz, max_mz, aggregator=np.sum, **kwargs):
# def get_heatmap(h5file, mz_bins, **kwargs):
# def get_spectrogram(h5file, min_rt, max_rt, bins=2000, **kwargs):
# def get_info(h5file):
# 
# 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/io/metatlas_get_data_helper_fun.py
import copy
import logging
import math
import os.path
import re
import sys
import dill
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import six
import tables
from collections import defaultdict
from textwrap import wrap
from metatlas.datastructures import metatlas_objects as metob
from metatlas.io import h5_query as h5q
from metatlas.io import write_utils

    second member to the tuple, which will not be used, such as ('attribute_name', 'as attribute')
    """
    if len(ids) == 0:
        raise ValueError('ids cannot be empty')
    if len(ids) == 1:
        if isinstance(ids[0], tuple):
            setattr(data, ids[0][0], value)
        elif isinstance(ids[0], str) and hasattr(data, ids[0]):
            setattr(data, ids[0], value)
        else:
            data[ids[0]] = value  # works for list or dict
    else:
        if isinstance(ids[0], tuple):
            set_nested(getattr(data, ids[0][0]), ids[1:], value)
        elif isinstance(ids[0], str) and hasattr(data, ids[0]):
            set_nested(getattr(data, ids[0]), ids[1:], value)
        else:
            set_nested(data[ids[0]], ids[1:], value)


def make_atlas_df(atlas):
    """
    inputs:
        atlas: metatlas.datastructures.metatlas_objects.Atlas
    output:
        pandas DataFrame with one row per CompoundIdentification in atlas and each row also includes
        the first RtReference, MzReference, and Compound from the CompoundIdentification
    """
    mzs = [extract(aci, ['mz_references', 0], metob.MzReference()) for aci in atlas.compound_identifications]
    rts = [extract(aci, ['rt_references', 0], metob.RtReference()) for aci in atlas.compound_identifications]

    compounds = [extract(aci, ['compound', 0], metob.Compound()) for aci in atlas.compound_identifications]