Beispiel #1
0
def tp_pars(some_str: str) -> List:
    """
    Функция для парсинга температуры и давленя в *.out файле

    Parameters
    ---------
    some_str: str

    Returns
    ------
    Список содержащий два объекта класса Setting,
    Температура и давление соответственно
    """
    _temperature = r'(Temperature)\s*([0-9.]+)\s*([\w]+).'
    _pressure = r'(Pressure)\s*([0-9.]+)\s*([\w]+).'
    tp_string = re.search(_temperature + r'\s*' + _pressure, some_str)
    if tp_string:
        return [
            Setting(name=tp_string.group(1),
                    value=tp_string.group(2),
                    unit=tp_string.group(3)),
            Setting(name=tp_string.group(4),
                    value=tp_string.group(5),
                    unit=tp_string.group(6))
        ]
Beispiel #2
0
def tsrot_pars(some_string: str):
    """Функция необходима для парсинга строк в которые входит TSrot
    (вращательная энтропия умноженная на температуру), на вход
    принимает строку в которой параметры указаны в kcal/mol,
    а возвращает объект класса Setting переконвертировав в J/mol.

    Parameters
    ---------
    some_string: str
        Строка содержащая в себе значение вращательной энтропии

    Returns
    ------
        Возвращает объект класса Setting, содержащий в себе
        значения TSrot в J/mol.
    """
    _sn_coef_ = r'sn=\s?([\d.]+)'
    _some_info_ = r'[\s]+qrot.sn=[\s]+[-\d.]+\s'
    _tsrot_segment_ = r'T\*S\(rot\)=[\s]+'
    _value_ = r'([-\d.]+)[\s]+kcal\/mol'
    _reg = re.search(_sn_coef_ + _some_info_ + _tsrot_segment_ + _value_,
                     some_string)
    if _reg:
        _sn_coef = _reg.group(1)
        _value = _reg.group(2)
        _unit = 'kcal/mol'
        return Setting(name=f'{_sn_coef} T*S(rot)', value=_value,
                       unit=_unit).convert(koef=4184, unit='J/mol')
Beispiel #3
0
def freq_pars(some_str: str) -> list:
    """
    Функция для парсинга частот

    Parameters
    ---------
    some_string: str
        Строка содержащая в себе значение частоты

    Return
    ------
        Возвращает список содержащий в себе объекты класса Setting,
        с значениями частот в cm**-1.
    """
    _current_freq_ = []
    _name_ = r'(\w+)'
    _freq_value_ = r'([-\d.]+)'
    _reg_str = _name_ + r'\s\-\-\s*'
    # Когда в строке не 3 частоты
    # Мы можем учесть это размером регулярного выражения
    for i in range(len(some_str.split()) - 2):
        _reg_str += _freq_value_ + r'\s*'
    freq_str = re.search(_reg_str, some_str)
    if freq_str:
        for i in range(2, len(some_str.split())):
            _current_freq_.append(
                Setting(name='freq.', value=freq_str.group(i), unit='cm**-1'))
    return _current_freq_
Beispiel #4
0
def name_value_pars(some_str: str):
    _name = r'([\w\s]+)'
    _dots = r'\s*[\.]+\s*'
    _value = r'([\d]+)'
    _reg = re.search(_name + _dots + _value, some_str)

    if _reg:
        return Setting(name=_reg.group(1), value=_reg.group(2), unit='')
Beispiel #5
0
def setting_pars(settings_str: str):
    # TODO Документация job_indx
    """Функция для извлечения параметров расчета из строк,
    принимает строку из *.tab файла, содержащую подстроку
    'Settings'

    Arguments
    ---------
    settings_str: str
        Строка *.tab файла, содержащая ключевое слово 'Settings'

    Return
    ------
    job_indx: str

    settings_list: tuple
        Кортеж содержащий объекты класса Setting, описывающие
        условия проведения расчета

    Example
    -------
    >>> setting_pars('Settings  job 2 : T= 223.15 K ; x(1)= 0.1000;')
    (2, (T= 223.15 K, x(1)= 0.1 %))
    """
    settings_list = []
    job_indx, new_line = settings_str.split(":")
    job_indx = job_indx.split()[2]
    settings = new_line.split(";")
    for setting in settings:
        new_setting = None
        if len(setting.split()) == 3:
            settings_list.append(Setting.from_record(setting))
        elif len(setting.split()) == 2:
            new_setting = Setting.from_record(setting)
            new_setting.convert(name=compound_nr(new_setting.name), unit="%")
            settings_list.append(new_setting)
        elif len(setting.split()) > 3:
            # TODO: Проблемное место, пофиксить n в chunkit
            for element in chunkit(setting.split(),
                                   n=len(setting.split()) / 2):
                new_setting = Setting.from_record(element)
                new_setting.convert(name=compound_nr(new_setting.name),
                                    unit="%")
                settings_list.append(new_setting)
    return int(job_indx), tuple(settings_list)
Beispiel #6
0
    def settings_df(self, detailed=None):
        # TODO Документация
        """
        """
        columns = [self.job_indx]
        index = [x.name for x in self.settings]

        if 'p=' in index:
            pass
        else:
            index.append('p=')
            self.settings.append(Setting(name='p=', value=1, unit='atm'))

        if detailed:
            data = self.settings
        else:
            data = [x.value for x in self.settings]

        return pd.DataFrame(columns=columns, index=index, data=data)
Beispiel #7
0
def freq_pars(some_str: str):
    """Функция для парсинга строк содержащих значения частот

    Parameters
    ---------
    some_string: str
        Строка содержащая в себе значение частоты

    Returns
    ------
        Возвращает объект класса Setting, содержащий в себе
        значения параметра в cm**-1.
    """
    _freq_number_ = r'([\d]+):\s+'
    _value_ = r'([-\d.]+)'
    _unit_ = r'\s(cm\**-1)'
    _reg = re.search(_freq_number_ + _value_ + _unit_, some_str)

    if _reg:
        return Setting(name='freq.', value=_reg.group(2), unit=_reg.group(3))
Beispiel #8
0
def molecular_mass_pars(some_str: str) -> Setting:
    """
    Функция для извлечения молекулярной массы

    Parameters
    ----------
    some_str : str
        Строка для парсинга

    Returns
    -------
    Setting
        Содержит название, значение и единицы измерения параметра
    """
    _mol_mass = r'Molecular mass:\s*([0-9.]+)\s*([\w]+).'
    _mol_mass_string = re.search(_mol_mass, some_str)
    if _mol_mass_string:
        return Setting(name='molecular mass',
                       value=_mol_mass_string.group(1),
                       unit=_mol_mass_string.group(2))
Beispiel #9
0
def scf_energy_pars(some_str: str):
    """
    Функция для извлечения электронной энергии

    Parameters
    ----------
    some_str : str
        Строка для парсинга

    Returns
    -------
    Setting
        Содержит название, значение и единицы измерения параметра
    """
    _scf_energy = r'SCF\sDone:\s*E[\w\d()-]*\s*=\s*([-\d.]*)'
    _scf_energy_string = re.search(_scf_energy, some_str)
    if _scf_energy_string:
        return Setting(name='scf energy',
                       value=_scf_energy_string.group(1),
                       unit='Eh').convert(koef=EH_JMOL, unit='J/mol')
Beispiel #10
0
def other_param_pars(some_string: str):
    """Функция предназначена для парсинга параметров, указанных в Eh,
    автоматически конвертирует их в J/mol

    Parameters
    ---------
    some_string: str
        Строка содержащая в себе значения вращательной энтропии

    Returns
    ------
        Возвращает объект класса Setting, содержащий в себе
        значения параметра в J/mol.
    """
    _name_ = r'([\w\s]+\w+)'
    _dots_ = r'\s*[\.]+\s*'
    _value_ = r'([-\d.]+)\s*.*'
    _reg = re.search(_name_ + _dots_ + _value_, some_string)

    if _reg:
        return Setting(name=_reg.group(1), value=_reg.group(2),
                       unit='Eh').convert(koef=EH_JMOL, unit='J/mol')
Beispiel #11
0
def properties_pars(some_str: str) -> Setting:
    """
    Извлекает значение и название типа энтропии из строки

    Parameters
    ----------
    some_str : str
        Строки типа: "Vibrational 120.478 27.641 25.420"

    Returns
    -------
    Setting
        Содержит название, значение в J/Mol*K, и единицы измерения
    """
    _name_ = some_str.split()[0]
    _value_ = r'([0-9]{1,10}\.[0-9]{3})'
    _whitespace_ = r'\s{2,15}'
    entropy_str = re.search(
        _value_ + _whitespace_ + _value_ + _whitespace_ + _value_, some_str)
    if entropy_str:
        return Setting(name=_name_ + ' entropy',
                       value=entropy_str.group(3),
                       unit='Cal/mol*K').convert(koef=4.184, unit='J/mol*K')
Beispiel #12
0
def parameter_pars(some_str: str) -> Setting:
    """Функция для парсинга термодинамических параметров, должна
    принимать строки содержащие в себе один элемент из списка
    PARAMETER_LIST

    Parameters
    ---------
    some_str: str
        Строка для парсинга

    Return
    ------
    Возвращает объект класса Setting, содержащий в себе термодинамические
    параметры в J/mol
    """
    _name_ = some_str.split('=')[0]
    _value_ = r'(-?[0-9]{1,10}\.[0-9]{6})'
    param_str = re.search(_value_, some_str)
    # coef = 4.359744 * 6.022e5
    # hartree_to_j_coef / N_Avogadro
    if param_str:
        return Setting(name=_name_[1:], value=param_str.group(1),
                       unit='Eh').convert(koef=EH_JMOL, unit='J/mol')
Beispiel #13
0
def tp_pars(some_string: str):
    """Функция для парсинга строк содержащих значения температуры и давления

    Parameters
    ---------
    some_string: str
        Строка содержащая в себе значение параметра
        (температура или давление)

    Returns
    ------
        Возвращает объект класса Setting, содержащий в себе
        значения параметра в J/mol.
    """
    _name_ = r'([\w\s]+)'
    _dots_ = r'\s*[\.]+\s*'
    _value_ = r'([\d]+.[\d]+)'
    _unit_ = r'\s*(\w+)'

    _reg = re.search(_name_ + _dots_ + _value_ + _unit_, some_string)
    if _reg:
        return Setting(name=_reg.group(1).split()[0],
                       value=_reg.group(2),
                       unit=_reg.group(3))
Beispiel #14
0
def post_process(element: Setting):

    if element.name.lower() == 'number of atoms':
        element.convert(name='natoms')
    elif element.name.lower() == 'total':
        element.convert(name='molecular mass')
    elif element.name.lower() == 'zero point energy':
        element.convert(name='zero-point energy')
    elif element.name.lower() == 'final gibbs free enthalpy':
        element.convert('sum of electronic and thermal free energies')
    elif element.name.lower() == 'total enthalpy':
        element.convert(name='sum of electronic and thermal enthalpies')
    elif element.name.lower() == 'electronic energy':
        element.convert(name='scf energy')
    elif 'THERMOCHEMISTRY AT' in element.name:
        element = None
    elif element.name.lower() == 'number of degrees of freedom':
        element.convert('deg. of freedom')
    elif element.name.lower() == 'freq.' and element.value == 0:
        element = None
    else:
        pass
    return element
Beispiel #15
0
def file_pars(file_path: str) -> pd.Series:
    """
    Принимает на вход путь к файлу, и парсит его, возвращая результаты в виде
    pandas.Series, если в файле не было данных или нужного файла не существует
    вылетит с ошибкой.

    Parameters
    ----------
    file_path : str
        Путь к файлу *.out

    Returns
    -------
    pd.Series
        Серия содержит термохимические и структурные параметры,
        необходимые для дальнейшего получения термодинамических данных
    """
    read_data = read_data_gaussian(file_path)
    _all_parameters = []
    if read_data:
        for line in read_data:
            if 'Frequencies' in line:
                _all_parameters.append(freq_pars(line))
            elif any(xs in line for xs in PARAMETER_LIST):
                _all_parameters.append(parameter_pars(line))
            elif any(xs in line for xs in PROPERTIES_LIST):
                _all_parameters.append(properties_pars(line))
            elif 'Temperature' in line:
                _all_parameters.append(tp_pars(line))
            elif 'Molecular mass' in line:
                _all_parameters.append(molecular_mass_pars(line))
            elif 'SCF Done' in line:
                _all_parameters.append(scf_energy_pars(line))
            elif 'NAtoms' in line:
                _all_parameters.append(
                    Setting(name='natoms', value=line.split()[1], unit='n'))
            elif 'Full point group' in line:
                sym_line = line.split()[3]
                _all_parameters.append(
                    Setting(name=line.split()[4],
                            value=line.split()[5],
                            unit=''))
            elif 'Deg. of freedom' in line:
                _all_parameters.append(
                    Setting(name='deg. of freedom',
                            value=line.split()[3],
                            unit=''))
            else:
                pass

    raw_data = list_unpack(_all_parameters)
    data = [parameter for parameter in raw_data if parameter is not None]
    # TODO Comments
    if data:
        indexes = [parameter.name for parameter in data]
        series = pd.Series(data=[x.value for x in data],
                           name='parameters',
                           index=indexes)
        series.loc['full point group'] = sym_line
        series.loc['qm_program'] = 'gaussian'
        if series.loc['natoms'] == 1:
            series.loc['atom'] = True
            series.loc['linear'] = True
        else:
            series.loc['atom'] = False
            if series.loc['deg. of freedom'] == 1:
                series.loc['linear'] = True
            elif series.loc[
                    'natoms'] > 1 and series.loc['natoms'] * 3 - 5 == len(
                        series.loc['freq.']):
                series.loc['linear'] = True
            else:
                series.loc['linear'] = False
        return series