<commit_before>"""Schemas to valid user input.

Index
-----
.. currentmodule:: nanoqm.workflows.schemas
.. autosummary::
    {autosummary}

API
---
{autodata}

"""
__all__ = [
    'schema_cp2k_general_settings',
    'schema_derivative_couplings',
    'schema_single_points',
    'schema_distribute_absorption_spectrum',
    'schema_distribute_derivative_couplings',
    'schema_distribute_single_points',
    'schema_absorption_spectrum',
    'schema_ipr',
    'schema_coop']

import os
from numbers import Real
from typing import Any, Dict, Iterable

import pkg_resources as pkg
from schema import And, Optional, Or, Regex, Schema, Use


def equal_lambda(name: str) -> And:
    """Create an schema checking that the keyword matches the expected value."""
    return And(
        str, Use(str.lower), lambda s: s == name)


def any_lambda(array: Iterable[str]) -> And:
    """Create an schema checking that the keyword matches one of the expected values."""
    return And(
        str, Use(str.lower), lambda s: s in array)


def merge(d1: Dict[str, Any], d2: Dict[str, Any]) -> Dict[str, Any]:
    """Merge two dictionaries using without modifying the original."""
    x = d1.copy()

    x.update(d2)

    return x


#: Schema to validate the CP2K general settings
schema_cp2k_general_settings = Schema({

    # "Basis set to carry out the quantum chemistry simulation"
    "basis": str,

    # "Pseudo-potential to carry out the quantum chemistry simulation"
    "potential": str,

    # Charge of the system
    Optional("charge", default=0): int,

    # Multiplicity
    Optional("multiplicity", default=1): int,

    # Specify the Cartesian components for the cell vector
    "cell_parameters": Or(
        Real,
        lambda xs: len(xs) == 3 and isinstance(xs, list),
        lambda xs: len(xs) == 3 and all(len(r) == 3 for r in xs)),

    # Type of periodicity
    "periodic": any_lambda(("none", "x", "y", "z", "xy", "xy", "yz", "xyz")),

    # Specify the angles between the vectors defining the unit cell
    Optional("cell_angles"): list,

    # Path to the folder containing the basis set specifications
    Optional("path_basis", default=pkg.resource_filename("nanoqm", "basis")): os.path.isdir,

    # Settings describing the input of the quantum package<commit_msg>make cell parameter optional<commit_after>"""Schemas to valid user input.

Index
-----
.. currentmodule:: nanoqm.workflows.schemas
.. autosummary::
    {autosummary}

API
---
{autodata}

"""
__all__ = [
    'schema_cp2k_general_settings',
    'schema_derivative_couplings',
    'schema_single_points',
    'schema_distribute_absorption_spectrum',
    'schema_distribute_derivative_couplings',
    'schema_distribute_single_points',
    'schema_absorption_spectrum',
    'schema_ipr',
    'schema_coop']

import os
from numbers import Real
from typing import Any, Dict, Iterable

import pkg_resources as pkg
from schema import And, Optional, Or, Regex, Schema, Use


def equal_lambda(name: str) -> And:
    """Create an schema checking that the keyword matches the expected value."""
    return And(
        str, Use(str.lower), lambda s: s == name)


def any_lambda(array: Iterable[str]) -> And:
    """Create an schema checking that the keyword matches one of the expected values."""
    return And(
        str, Use(str.lower), lambda s: s in array)


def merge(d1: Dict[str, Any], d2: Dict[str, Any]) -> Dict[str, Any]:
    """Merge two dictionaries using without modifying the original."""
    x = d1.copy()

    x.update(d2)

    return x


#: Schema to validate the CP2K general settings
schema_cp2k_general_settings = Schema({

    # "Basis set to carry out the quantum chemistry simulation"
    "basis": str,

    # "Pseudo-potential to carry out the quantum chemistry simulation"
    "potential": str,

    # Charge of the system
    Optional("charge", default=0): int,

    # Multiplicity
    Optional("multiplicity", default=1): int,

    # Specify the Cartesian components for the cell vector Units Angstrom
    Optional("cell_parameters", default=10): Or(
        Real,
        lambda xs: len(xs) == 3 and isinstance(xs, list),
        lambda xs: len(xs) == 3 and all(len(r) == 3 for r in xs)),

    # Type of periodicity
    "periodic": any_lambda(("none", "x", "y", "z", "xy", "xy", "yz", "xyz")),

    # Specify the angles between the vectors defining the unit cell
    Optional("cell_angles"): list,

    # Path to the folder containing the basis set specifications
    Optional("path_basis", default=pkg.resource_filename("nanoqm", "basis")): os.path.isdir,

    # Settings describing the input of the quantum package
{'fraction_non_alphanumeric': 0.11779991338241663, 'fraction_numerical': 0.00563014291901256, 'mean_word_length': 3.6703741152679474, 'pattern_counts': {'":': 7, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2983639', 'n_tokens_mistral': 1473, 'n_tokens_neox': 1393, 'n_words': 471}