# Path: utility/getdata.py
# DEFAULT_SETUP = 'getdata_setup.xml'
# class GetData(AccessData):
#     def __init__(self,
#                  data_path_name=None,
#                  data_key=[],
#                  data_format="pandas"):
#     def read_data(self):
#     def read_h5_to_pandas(self):
#     def read_h5_to_array(self):
#     def read_txt_to_str(self):
#     def read_txt_to_array(self):
#     def read_xml(self):
#     def get_data(self):
#     def download_private_data(self):
#     def download_public_data(self):
#     def ensure_dir(file_path):
# 
# Path: crm_solver/neutral_db.py
# class NeutralDB(object):
#     def __init__(self, param=None, components=None, resolved=None):
#         self.param = param
#         self.__set_atomic_resolution(resolved=resolved)
#         self.__load_neutral_cross_section(components=components)
#         self.__get_atomic_levels()
# 
#     def __set_atomic_resolution(self, resolved):
#         projectile = self.param.getroot().find('body').find('beamlet_species').text
#         if resolved is None:
#             if projectile == 'H' or projectile == 'D' or projectile == 'T':
#                 self.resolved = 'bundled_n'
#             elif projectile == 'Li' or projectile == 'Na':
#                 self.resolved = 'nl'
#         else:
#             self.resolved = resolved
# 
#     def __create_neutral_cross_section_db(self, components):
#         self.neutral_cross_sections = {}
#         self.neutral_target_count = len([comp for comp in components['q'] if int(comp) == 0])
#         for index in range(self.neutral_target_count):
#             self.neutral_cross_sections.update({'neutral'+str(index+1): None})
# 
#     def __set_neutral_cross_section_path(self, target='H'):
#         file_name = target + '_' + self.resolved + '_' + \
#                     self.param.getroot().find('body').find('beamlet_energy').text + '.txt'
# 
#         return os.path.join('atomic_data', self.param.getroot().find('body').find('beamlet_species').text,
#                             'cross_sections', 'neutral', file_name)
# 
#     def __identify_neutral_target(self, component):
#         if isinstance(component['Molecule'], str):
#             return component['Molecule']
#         else:
#             if component['Z'] == 1 and component['A'] == 1:
#                 return 'H'
#             elif component['Z'] == 1 and component['A'] == 2:
#                 return 'D'
#             elif component['Z'] == 1 and component['A'] == 3:
#                 return 'T'
#             else:
#                 raise NotImplementedError('The requested atomic gas is not supported yet.')
# 
#     def __load_neutral_cross_section(self, components):
#         self.__create_neutral_cross_section_db(components=components)
#         for index in range(self.neutral_target_count):
#             name = 'neutral'+str(index+1)
#             target = self.__identify_neutral_target(component=components.T[name])
#             path = self.__set_neutral_cross_section_path(target=target)
#             self.neutral_cross_sections[name] = GetData(data_path_name=path, data_format="array").data
# 
#     def __get_atomic_levels(self):
#         for index in range(self.neutral_target_count):
#             atomic_levels = self.neutral_cross_sections['neutral'+str(index+1)].shape[0]
#             if not hasattr(self, 'atomic_level'):
#                 self.atomic_levels = atomic_levels
#             elif self.atomic_levels > atomic_levels:
#                 self.atomic_levels = atomic_levels
# 
#     def get_neutral_impact_loss(self, target, from_level):
#         return uc.convert_from_cm2_to_m2(self.neutral_cross_sections[target][from_level, from_level])
# 
#     def get_neutral_impact_transition(self, target, from_level, to_level):
#         if from_level == to_level:
#             raise RenateNotValidTransitionError('The requested atomic transition is not valid. '
#                                                 'Requested transition is an ionization.')
#         return uc.convert_from_cm2_to_m2(self.neutral_cross_sections[target][from_level, to_level])


import os
import numpy
import utility.convert as uc
import matplotlib.pyplot as plt
import pandas
from lxml import etree
from utility import getdata
from scipy.interpolate import interp1d
from crm_solver.neutral_db import NeutralDB
            return self.load_rate_data(self.rates_path, 'Collisional Coeffs/Proton Neutral Collisions')
        elif source == 'impurity_transition':
            return self.load_rate_data(self.rates_path, 'Collisional Coeffs/Impurity Neutral Collisions')
        elif source == 'ionization_terms':
            return self.load_rate_data(self.rates_path, 'Collisional Coeffs/Electron Loss Collisions')
        elif source == 'spontaneous_transition':
            return self.load_rate_data(self.rates_path, 'Einstein Coeffs')
        elif source == 'temperature':
            return self.load_rate_data(self.rates_path, 'Temperature axis')
        else:
            raise ValueError('Data ' + source + ' is not located and supported in the Renate rate library.')


class AtomicDB(RenateDB):
    def __init__(self, atomic_source='renate', param=None, rate_type='default', resolution=None,
                 data_path='beamlet/testimp0001.xml', components=None, atomic_ceiling=False):
        assert isinstance(atomic_source, str)
        assert isinstance(components, pandas.core.frame.DataFrame)
        self.components = components
        self.__set_neutral_db(param=param, resolution=resolution)
        if atomic_source == 'renate':
            RenateDB.__init__(self, param, rate_type, data_path)
            self.__set_ceiling_for_atomic_levels(atomic_ceiling=atomic_ceiling)
            self.__generate_rate_function_db()
        else:
            raise ValueError('Currently the requested atomic DB: ' + atomic_source + ' is not supported')

    def __set_neutral_db(self, param, resolution):
        if (self.components['q'] == 0).any():
            self.are_neutrals = True

# Path: utility/getdata.py
# DEFAULT_SETUP = 'getdata_setup.xml'
# class GetData(AccessData):
#     def __init__(self,
#                  data_path_name=None,
#                  data_key=[],
#                  data_format="pandas"):
#     def read_data(self):
#     def read_h5_to_pandas(self):
#     def read_h5_to_array(self):
#     def read_txt_to_str(self):
#     def read_txt_to_array(self):
#     def read_xml(self):
#     def get_data(self):
#     def download_private_data(self):
#     def download_public_data(self):
#     def ensure_dir(file_path):
# 
# Path: crm_solver/neutral_db.py
# class NeutralDB(object):
#     def __init__(self, param=None, components=None, resolved=None):
#         self.param = param
#         self.__set_atomic_resolution(resolved=resolved)
#         self.__load_neutral_cross_section(components=components)
#         self.__get_atomic_levels()
# 
#     def __set_atomic_resolution(self, resolved):
#         projectile = self.param.getroot().find('body').find('beamlet_species').text
#         if resolved is None:
#             if projectile == 'H' or projectile == 'D' or projectile == 'T':
#                 self.resolved = 'bundled_n'
#             elif projectile == 'Li' or projectile == 'Na':
#                 self.resolved = 'nl'
#         else:
#             self.resolved = resolved
# 
#     def __create_neutral_cross_section_db(self, components):
#         self.neutral_cross_sections = {}
#         self.neutral_target_count = len([comp for comp in components['q'] if int(comp) == 0])
#         for index in range(self.neutral_target_count):
#             self.neutral_cross_sections.update({'neutral'+str(index+1): None})
# 
#     def __set_neutral_cross_section_path(self, target='H'):
#         file_name = target + '_' + self.resolved + '_' + \
#                     self.param.getroot().find('body').find('beamlet_energy').text + '.txt'
# 
#         return os.path.join('atomic_data', self.param.getroot().find('body').find('beamlet_species').text,
#                             'cross_sections', 'neutral', file_name)
# 
#     def __identify_neutral_target(self, component):
#         if isinstance(component['Molecule'], str):
#             return component['Molecule']
#         else:
#             if component['Z'] == 1 and component['A'] == 1:
#                 return 'H'
#             elif component['Z'] == 1 and component['A'] == 2:
#                 return 'D'
#             elif component['Z'] == 1 and component['A'] == 3:
#                 return 'T'
#             else:
#                 raise NotImplementedError('The requested atomic gas is not supported yet.')
# 
#     def __load_neutral_cross_section(self, components):
#         self.__create_neutral_cross_section_db(components=components)
#         for index in range(self.neutral_target_count):
#             name = 'neutral'+str(index+1)
#             target = self.__identify_neutral_target(component=components.T[name])
#             path = self.__set_neutral_cross_section_path(target=target)
#             self.neutral_cross_sections[name] = GetData(data_path_name=path, data_format="array").data
# 
#     def __get_atomic_levels(self):
#         for index in range(self.neutral_target_count):
#             atomic_levels = self.neutral_cross_sections['neutral'+str(index+1)].shape[0]
#             if not hasattr(self, 'atomic_level'):
#                 self.atomic_levels = atomic_levels
#             elif self.atomic_levels > atomic_levels:
#                 self.atomic_levels = atomic_levels
# 
#     def get_neutral_impact_loss(self, target, from_level):
#         return uc.convert_from_cm2_to_m2(self.neutral_cross_sections[target][from_level, from_level])
# 
#     def get_neutral_impact_transition(self, target, from_level, to_level):
#         if from_level == to_level:
#             raise RenateNotValidTransitionError('The requested atomic transition is not valid. '
#                                                 'Requested transition is an ionization.')
#         return uc.convert_from_cm2_to_m2(self.neutral_cross_sections[target][from_level, to_level])


# Path: crm_solver/atomic_db.py
import os
import numpy
import utility.convert as uc
import matplotlib.pyplot as plt
import pandas
from lxml import etree
from utility import getdata
from scipy.interpolate import interp1d
from crm_solver.neutral_db import NeutralDB

            return self.load_rate_data(self.rates_path, 'Collisional Coeffs/Proton Neutral Collisions')
        elif source == 'impurity_transition':
            return self.load_rate_data(self.rates_path, 'Collisional Coeffs/Impurity Neutral Collisions')
        elif source == 'ionization_terms':
            return self.load_rate_data(self.rates_path, 'Collisional Coeffs/Electron Loss Collisions')
        elif source == 'spontaneous_transition':
            return self.load_rate_data(self.rates_path, 'Einstein Coeffs')
        elif source == 'temperature':
            return self.load_rate_data(self.rates_path, 'Temperature axis')
        else:
            raise ValueError('Data ' + source + ' is not located and supported in the Renate rate library.')


class AtomicDB(RenateDB):
    def __init__(self, atomic_source='renate', param=None, rate_type='default', resolution=None,
                 data_path='beamlet/testimp0001.xml', components=None, atomic_ceiling=False):
        assert isinstance(atomic_source, str)
        assert isinstance(components, pandas.core.frame.DataFrame)
        self.components = components
        self.__set_neutral_db(param=param, resolution=resolution)
        if atomic_source == 'renate':
            RenateDB.__init__(self, param, rate_type, data_path)
            self.__set_ceiling_for_atomic_levels(atomic_ceiling=atomic_ceiling)
            self.__generate_rate_function_db()
        else:
            raise ValueError('Currently the requested atomic DB: ' + atomic_source + ' is not supported')

    def __set_neutral_db(self, param, resolution):
        if (self.components['q'] == 0).any():
            self.are_neutrals = True

            self.neutral_db = NeutralDB(param=param, resolved=resolution, components=self.components)