Statistiques
| Branche: | Tag: | Révision :

dockonsurf / modules / dos_input.py @ cea7af64

Historique | Voir | Annoter | Télécharger (32,45 ko)

1 b77be9ad Carles
"""Functions to deal with DockOnSurf input files.
2 b77be9ad Carles

3 b77be9ad Carles
Functions
4 0e83e6a6 Carles
try_command:Tries to run a command and logs its exceptions (expected and not).
5 0e83e6a6 Carles
str2lst: Converts a string of integers, and groups of them, to a list of lists.
6 0e83e6a6 Carles
check_expect_val: Checks whether the value of an option has an adequate value.
7 0e83e6a6 Carles
read_input: Sets up the calculation by reading the parameters from input file.
8 0e83e6a6 Carles
get_run_type: Gets 'run_type' value and checks that its value is acceptable.
9 0e83e6a6 Carles
get_code: Gets 'code' value and checks that its value is acceptable.
10 0e83e6a6 Carles
get_batch_q_sys: Gets 'batch_q_sys' value and checks that its value is
11 8887f41d Carles
acceptable.
12 0e83e6a6 Carles
get_relaunch_err: Gets 'relaunch_err' value and checks that its value is
13 8887f41d Carles
acceptable.
14 09c3325a Carles Marti
get_max_jobs: Gets 'max_jobs' value and checks that its value is acceptable.
15 0e83e6a6 Carles
get_special_atoms: Gets 'special_atoms' value and checks that its value is
16 8887f41d Carles
acceptable.
17 0e83e6a6 Carles
get_isol_inp_file: Gets 'isol_inp_file' value and checks that its value is
18 8887f41d Carles
acceptable.
19 0e83e6a6 Carles
get_cluster_magns: Gets 'cluster_magns' value and checks that its value is
20 8887f41d Carles
acceptable.
21 0e83e6a6 Carles
get_num_conformers: Gets 'num_conformers' value and checks that its value is
22 8887f41d Carles
acceptable.
23 0e83e6a6 Carles
get_num_prom_cand: Gets 'num_prom_cand' value and checks that its value is
24 8887f41d Carles
acceptable.
25 a5c74494 Carles
get_iso_rmsd: Gets 'iso_rmsd' value and checks that its value is acceptable.
26 4670488d Carles Marti
get_pre_opt: Gets 'pre_opt' value and checks that its value is acceptable.
27 0e83e6a6 Carles
get_screen_inp_file: Gets 'screen_inp_file' value and checks that its value is
28 8887f41d Carles
acceptable.
29 0e83e6a6 Carles
get_sites: Gets 'sites' value and checks that its value is acceptable.
30 7dd94df7 Carles Marti
get_molec_ctrs: Gets 'molec_ctrs' value and checks that its value is
31 8887f41d Carles
acceptable.
32 0e83e6a6 Carles
get_try_disso: Gets 'try_disso' value and checks that its value is acceptable.
33 0e83e6a6 Carles
get_pts_per_angle: Gets 'pts_per_angle' value and checks that its value is
34 8887f41d Carles
acceptable.
35 0e83e6a6 Carles
get_coll_thrsld: Gets 'coll_thrsld' value and checks that its value is
36 8887f41d Carles
acceptable.
37 0e83e6a6 Carles
get_screen_rmsd: Gets 'screen_rmsd' value and checks that its value is
38 8887f41d Carles
acceptable.
39 0e83e6a6 Carles
get_coll_bottom_z: Gets 'coll_bottom_z' value and checks that its value is
40 8887f41d Carles
acceptable.
41 0e83e6a6 Carles
get_refine_inp_file: Gets 'refine_inp_file' value and checks that its value is
42 8887f41d Carles
acceptable.
43 0e83e6a6 Carles
get_energy_cutoff: Gets 'energy_cutoff' value and checks that its value is
44 8887f41d Carles
acceptable.
45 17e72a49 Carles
"""
46 8887f41d Carles
import os.path
47 b5b2af64 Carles
import logging
48 8887f41d Carles
from configparser import ConfigParser, NoSectionError, NoOptionError, \
49 8887f41d Carles
    MissingSectionHeaderError, DuplicateOptionError
50 5fb01677 Carles Marti
import numpy as np
51 af3e2441 Carles Marti
from modules.utilities import try_command
52 8887f41d Carles
53 8887f41d Carles
logger = logging.getLogger('DockOnSurf')
54 8887f41d Carles
55 8887f41d Carles
dos_inp = ConfigParser(inline_comment_prefixes='#',
56 8887f41d Carles
                       empty_lines_in_values=False)
57 8887f41d Carles
58 8887f41d Carles
new_answers = {'n': False, 'none': False, 'nay': False,
59 8887f41d Carles
               'y': True, '': True, 'aye': True, 'sure': True}
60 8887f41d Carles
for answer, val in new_answers.items():
61 8887f41d Carles
    dos_inp.BOOLEAN_STATES[answer] = val
62 8887f41d Carles
turn_false_answers = [answer for answer in dos_inp.BOOLEAN_STATES
63 8887f41d Carles
                      if dos_inp.BOOLEAN_STATES[answer] is False]
64 8887f41d Carles
65 8887f41d Carles
no_sect_err = "Section '%s' not found on input file"
66 8887f41d Carles
no_opt_err = "Option '%s' not found on section '%s'"
67 8887f41d Carles
num_error = "'%s' value must be a %s"
68 8887f41d Carles
69 4533134f Carles Marti
70 4533134f Carles Marti
def str2lst(cmplx_str, func=int):  # TODO: enable deeper level of nested lists
71 a7128ce1 Carles Marti
    # TODO Treat all-enclosing parenthesis as a list instead of list of lists.
72 b77be9ad Carles
    """Converts a string of integers, and groups of them, to a list.
73 b77be9ad Carles

74 b77be9ad Carles
    Keyword arguments:
75 4533134f Carles Marti
    @param cmplx_str: str, string of integers (or floats) and groups of them
76 4533134f Carles Marti
    enclosed by parentheses-like characters.
77 b77be9ad Carles
    - Group enclosers: '()' '[]' and '{}'.
78 4533134f Carles Marti
    - Separators: ',' ';' and ' '.
79 b77be9ad Carles
    - Nested groups are not allowed: '3 ((6 7) 8) 4'.
80 4533134f Carles Marti
    @param func: either to use int or float
81 b77be9ad Carles

82 4533134f Carles Marti
    @return list, list of integers (or floats), or list of integers (or floats)
83 4533134f Carles Marti
    in the case they were grouped. First, the singlets are placed, and then the
84 4533134f Carles Marti
    groups in input order.
85 b77be9ad Carles

86 b77be9ad Carles
    eg. '128,(135 138;141] 87 {45, 68}' -> [128, 87, [135, 138, 141], [45, 68]]
87 17e72a49 Carles
    """
88 b77be9ad Carles
89 8887f41d Carles
    # Checks
90 5261a07f Carles Marti
    error_msg = "Function argument should be a str, sequence of " \
91 8887f41d Carles
                "numbers separated by ',' ';' or ' '." \
92 79e3db42 Carles
                "\nThey can be grouped in parentheses-like enclosers: '()', " \
93 79e3db42 Carles
                "'[]' or {}. Nested groups are not allowed. \n" \
94 79e3db42 Carles
                "eg. 128,(135 138;141) 87 {45, 68}"
95 8887f41d Carles
    cmplx_str = try_command(cmplx_str.replace, [(AttributeError, error_msg)],
96 8887f41d Carles
                            ',', ' ')
97 8887f41d Carles
98 8887f41d Carles
    cmplx_str = cmplx_str.replace(';', ' ').replace('[', '(').replace(
99 8887f41d Carles
        ']', ')').replace('{', '(').replace('}', ')')
100 8887f41d Carles
101 4533134f Carles Marti
    try_command(list, [(ValueError, error_msg)], map(func, cmplx_str.replace(
102 8887f41d Carles
        ')', '').replace('(', '').split()))
103 8887f41d Carles
104 b5b2af64 Carles
    deepness = 0
105 b5b2af64 Carles
    for el in cmplx_str.split():
106 b5b2af64 Carles
        if '(' in el:
107 b5b2af64 Carles
            deepness += 1
108 b5b2af64 Carles
        if ')' in el:
109 b5b2af64 Carles
            deepness += -1
110 b5b2af64 Carles
        if deepness > 1 or deepness < 0:
111 9f7bb440 Carles
            logger.error(error_msg)
112 b5b2af64 Carles
            raise ValueError(error_msg)
113 17e72a49 Carles
114 772b40e5 Carles
    init_list = cmplx_str.split()
115 772b40e5 Carles
    start_group = []
116 772b40e5 Carles
    end_group = []
117 772b40e5 Carles
    for i, element in enumerate(init_list):
118 73402e22 Carles
        if '(' in element:
119 772b40e5 Carles
            start_group.append(i)
120 17e72a49 Carles
            init_list[i] = element.replace('(', '')
121 73402e22 Carles
        if ')' in element:
122 772b40e5 Carles
            end_group.append(i)
123 17e72a49 Carles
            init_list[i] = element.replace(')', '')
124 772b40e5 Carles
125 4533134f Carles Marti
    init_list = list(map(func, init_list))
126 772b40e5 Carles
127 17e72a49 Carles
    new_list = []
128 772b40e5 Carles
    for start_el, end_el in zip(start_group, end_group):
129 17e72a49 Carles
        new_list.append(init_list[start_el:end_el + 1])
130 772b40e5 Carles
131 772b40e5 Carles
    for v in new_list:
132 772b40e5 Carles
        for el in v:
133 772b40e5 Carles
            init_list.remove(el)
134 772b40e5 Carles
    return init_list + new_list
135 772b40e5 Carles
136 17e72a49 Carles
137 5f9f1400 Carles Marti
def check_expect_val(value, expect_vals, err_msg=None):
138 b77be9ad Carles
    """Checks whether an option lies within its expected values.
139 b77be9ad Carles

140 b77be9ad Carles
    Keyword arguments:
141 b77be9ad Carles
    @param value: The variable to check if its value lies within the expected
142 b77be9ad Carles
    ones
143 b77be9ad Carles
    @param expect_vals: list, list of values allowed for the present option.
144 5f9f1400 Carles Marti
    @param err_msg: The error message to be prompted in both log and screen.
145 b77be9ad Carles
    @raise ValueError: if the value is not among the expected ones.
146 b77be9ad Carles
    @return True if the value is among the expected ones.
147 b77be9ad Carles
    """
148 5f9f1400 Carles Marti
    if err_msg is None:
149 5f9f1400 Carles Marti
        err_msg = f"'{value}' is not an adequate value.\n" \
150 5f9f1400 Carles Marti
                  f"Adequate values: {expect_vals}"
151 821dca42 Carles Marti
    if not any([exp_val == value for exp_val in expect_vals]):
152 5f9f1400 Carles Marti
        logger.error(err_msg)
153 5f9f1400 Carles Marti
        raise ValueError(err_msg)
154 b77be9ad Carles
155 b77be9ad Carles
    return True
156 b77be9ad Carles
157 b77be9ad Carles
158 03fab2dd Carles
def check_inp_file(inp_file, code):
159 03fab2dd Carles
    if code == 'cp2k':
160 03fab2dd Carles
        from pycp2k import CP2K
161 03fab2dd Carles
        cp2k = CP2K()
162 03fab2dd Carles
        try_command(cp2k.parse,
163 03fab2dd Carles
                    [(UnboundLocalError, "Invalid CP2K input file")], inp_file)
164 03fab2dd Carles
165 03fab2dd Carles
166 a7128ce1 Carles Marti
# Global
167 a7128ce1 Carles Marti
168 8887f41d Carles
def get_run_type():
169 b1d27be5 Carles
    isolated, screening, refinement = (False, False, False)
170 5cc4994b Carles
    run_type_vals = ['isolated', 'screening', 'refinement', 'adsorption',
171 5cc4994b Carles
                     'full']
172 081548a0 Carles Marti
    run_types = dos_inp.get('Global', 'run_type').split()
173 081548a0 Carles Marti
    for run_type in run_types:
174 081548a0 Carles Marti
        check_expect_val(run_type.lower(), run_type_vals)
175 081548a0 Carles Marti
        if 'isol' in run_type.lower():
176 081548a0 Carles Marti
            isolated = True
177 081548a0 Carles Marti
        if 'screen' in run_type.lower():
178 081548a0 Carles Marti
            screening = True
179 081548a0 Carles Marti
        if 'refine' in run_type.lower():
180 081548a0 Carles Marti
            refinement = True
181 081548a0 Carles Marti
        if 'adsor' in run_type.lower():
182 081548a0 Carles Marti
            screening, refinement = (True, True)
183 081548a0 Carles Marti
        if 'full' in run_type.lower():
184 081548a0 Carles Marti
            isolated, screening, refinement = (True, True, True)
185 5cc4994b Carles
186 8887f41d Carles
    return isolated, screening, refinement
187 17e72a49 Carles
188 8887f41d Carles
189 8887f41d Carles
def get_code():
190 772b40e5 Carles
    code_vals = ['cp2k']
191 5cc4994b Carles
    check_expect_val(dos_inp.get('Global', 'code').lower(), code_vals)
192 5cc4994b Carles
    code = dos_inp.get('Global', 'code').lower()
193 8887f41d Carles
    return code
194 8887f41d Carles
195 17e72a49 Carles
196 8887f41d Carles
def get_batch_q_sys():
197 ec5bba46 Carles Marti
    batch_q_sys_vals = ['sge', 'lsf', 'irene', 'local'] + turn_false_answers
198 5cc4994b Carles
    check_expect_val(dos_inp.get('Global', 'batch_q_sys').lower(),
199 5cc4994b Carles
                     batch_q_sys_vals)
200 5cc4994b Carles
    batch_q_sys = dos_inp.get('Global', 'batch_q_sys').lower()
201 821dca42 Carles Marti
    if batch_q_sys.lower() in turn_false_answers:
202 821dca42 Carles Marti
        return False
203 821dca42 Carles Marti
    else:
204 821dca42 Carles Marti
        return batch_q_sys
205 17e72a49 Carles
206 8887f41d Carles
207 99afde40 Carles
def get_subm_script():
208 99afde40 Carles
    subm_script = dos_inp.get('Global', 'subm_script', fallback=False)
209 99afde40 Carles
    if subm_script and not os.path.isfile(subm_script):
210 695dcff8 Carles Marti
        logger.error(f'File {subm_script} not found.')
211 99afde40 Carles
        raise FileNotFoundError(f'File {subm_script} not found')
212 99afde40 Carles
    return subm_script
213 99afde40 Carles
214 99afde40 Carles
215 99afde40 Carles
def get_project_name():
216 bd573212 Carles
    project_name = dos_inp.get('Global', 'project_name', fallback='')
217 99afde40 Carles
    return project_name
218 99afde40 Carles
219 99afde40 Carles
220 8887f41d Carles
def get_relaunch_err():
221 09c3325a Carles Marti
    relaunch_err_vals = ['geo_not_conv']
222 b1d27be5 Carles
    relaunch_err = dos_inp.get('Global', 'relaunch_err',
223 17e72a49 Carles
                               fallback="False")
224 b1d27be5 Carles
    if relaunch_err.lower() in turn_false_answers:
225 8887f41d Carles
        return False
226 79e3db42 Carles
    else:
227 79e3db42 Carles
        check_expect_val(relaunch_err.lower(), relaunch_err_vals)
228 8887f41d Carles
    return relaunch_err
229 8887f41d Carles
230 8887f41d Carles
231 09c3325a Carles Marti
def get_max_jobs():
232 09c3325a Carles Marti
    err_msg = num_error % ('max_jobs', 'positive integer')
233 09c3325a Carles Marti
    max_jobs = try_command(dos_inp.getint, [(ValueError, err_msg)],
234 70fa4e74 Carles Marti
                           'Global', 'max_jobs', fallback=3)
235 09c3325a Carles Marti
236 09c3325a Carles Marti
    if max_jobs < 1:
237 09c3325a Carles Marti
        logger.error(num_error % ('max_jobs', 'positive integer'))
238 09c3325a Carles Marti
        raise ValueError(num_error % ('max_jobs', 'positive integer'))
239 09c3325a Carles Marti
    return max_jobs
240 09c3325a Carles Marti
241 09c3325a Carles Marti
242 09c3325a Carles Marti
def get_type_max():
243 09c3325a Carles Marti
    running = ['r', 'run', 'running']
244 09c3325a Carles Marti
    pending = ['p', 'pending', 'q', 'qw', 'queued']
245 09c3325a Carles Marti
    type_max = dos_inp.get('Global', 'type_max', fallback="False")
246 75d6a31b Carles Marti
    if type_max.lower() in turn_false_answers:
247 09c3325a Carles Marti
        return False
248 75d6a31b Carles Marti
    elif type_max.lower() in running:
249 09c3325a Carles Marti
        return 'r'
250 75d6a31b Carles Marti
    elif type_max.lower() in pending:
251 09c3325a Carles Marti
        return 'p'
252 09c3325a Carles Marti
    else:
253 ad57fd42 Carles Marti
        err = f"Value for 'type_max' is not accepted. Accepted values: " \
254 70fa4e74 Carles Marti
              f"{running + pending + turn_false_answers}."
255 09c3325a Carles Marti
        logger.error(err)
256 09c3325a Carles Marti
        raise ValueError(err)
257 17e72a49 Carles
258 8887f41d Carles
259 8887f41d Carles
def get_special_atoms():
260 8887f41d Carles
    from ase.data import chemical_symbols
261 17e72a49 Carles
262 5cc4994b Carles
    spec_at_err = '\'special_atoms\' does not have an adequate format.\n' \
263 5cc4994b Carles
                  'Adequate format: (Fe1 Fe) (O1 O)'
264 5cc4994b Carles
    special_atoms = dos_inp.get('Global', 'special_atoms', fallback="False")
265 b1d27be5 Carles
    if special_atoms.lower() in turn_false_answers:
266 90819cc3 Carles Marti
        special_atoms = []
267 b1d27be5 Carles
    else:
268 8949edd0 Carles
        # Converts the string into a list of tuples
269 8949edd0 Carles
        lst_tple = [tuple(pair.replace("(", "").split()) for pair in
270 b1d27be5 Carles
                    special_atoms.split(")")[:-1]]
271 5cc4994b Carles
        if len(lst_tple) == 0:
272 9f7bb440 Carles
            logger.error(spec_at_err)
273 5cc4994b Carles
            raise ValueError(spec_at_err)
274 9f7bb440 Carles
        for i, tup in enumerate(lst_tple):
275 90819cc3 Carles Marti
            if not isinstance(tup, tuple) or len(tup) != 2:
276 9f7bb440 Carles
                logger.error(spec_at_err)
277 5cc4994b Carles
                raise ValueError(spec_at_err)
278 5cc4994b Carles
            if tup[1].capitalize() not in chemical_symbols:
279 5cc4994b Carles
                elem_err = "The second element of the couple should be an " \
280 9f7bb440 Carles
                           "actual element of the periodic table"
281 9f7bb440 Carles
                logger.error(elem_err)
282 5cc4994b Carles
                raise ValueError(elem_err)
283 9f7bb440 Carles
            if tup[0].capitalize() in chemical_symbols:
284 9f7bb440 Carles
                elem_err = "The first element of the couple is already an " \
285 9f7bb440 Carles
                           "actual element of the periodic table, "
286 9f7bb440 Carles
                logger.error(elem_err)
287 9f7bb440 Carles
                raise ValueError(elem_err)
288 9f7bb440 Carles
            for j, tup2 in enumerate(lst_tple):
289 9f7bb440 Carles
                if j <= i:
290 9f7bb440 Carles
                    continue
291 9f7bb440 Carles
                if tup2[0] == tup[0]:
292 9f7bb440 Carles
                    label_err = f'You have specified the label {tup[0]} to ' \
293 8887f41d Carles
                                f'more than one special atom'
294 9f7bb440 Carles
                    logger.error(label_err)
295 9f7bb440 Carles
                    raise ValueError(label_err)
296 b1d27be5 Carles
        special_atoms = lst_tple
297 8887f41d Carles
    return special_atoms
298 8887f41d Carles
299 8887f41d Carles
300 a7128ce1 Carles Marti
# Isolated
301 a7128ce1 Carles Marti
302 8887f41d Carles
def get_isol_inp_file():
303 8887f41d Carles
    isol_inp_file = dos_inp.get('Isolated', 'isol_inp_file')
304 8887f41d Carles
    if not os.path.isfile(isol_inp_file):
305 695dcff8 Carles Marti
        logger.error(f'File {isol_inp_file} not found.')
306 8887f41d Carles
        raise FileNotFoundError(f'File {isol_inp_file} not found')
307 8887f41d Carles
    return isol_inp_file
308 8887f41d Carles
309 8887f41d Carles
310 95dc2c8e Carles
def get_molec_file():
311 95dc2c8e Carles
    molec_file = dos_inp.get('Isolated', 'molec_file')
312 95dc2c8e Carles
    if not os.path.isfile(molec_file):
313 695dcff8 Carles Marti
        logger.error(f'File {molec_file} not found.')
314 95dc2c8e Carles
        raise FileNotFoundError(f'File {molec_file} not found')
315 95dc2c8e Carles
    return molec_file
316 95dc2c8e Carles
317 95dc2c8e Carles
318 8887f41d Carles
def get_num_conformers():
319 8887f41d Carles
    err_msg = num_error % ('num_conformers', 'positive integer')
320 8887f41d Carles
    num_conformers = try_command(dos_inp.getint, [(ValueError, err_msg)],
321 8887f41d Carles
                                 'Isolated', 'num_conformers', fallback=100)
322 8887f41d Carles
    if num_conformers < 1:
323 8887f41d Carles
        logger.error(err_msg)
324 8887f41d Carles
        raise ValueError(err_msg)
325 8887f41d Carles
    return num_conformers
326 8887f41d Carles
327 8887f41d Carles
328 4670488d Carles Marti
def get_pre_opt():
329 4670488d Carles Marti
    pre_opt_vals = ['uff', 'mmff'] + turn_false_answers
330 4670488d Carles Marti
    check_expect_val(dos_inp.get('Isolated', 'pre_opt').lower(), pre_opt_vals)
331 ad57fd42 Carles Marti
    pre_opt = dos_inp.get('Isolated', 'pre_opt').lower()
332 ad57fd42 Carles Marti
    if pre_opt in turn_false_answers:
333 4670488d Carles Marti
        return False
334 4670488d Carles Marti
    else:
335 4670488d Carles Marti
        return pre_opt
336 b1f6e69d Carles
337 70fa4e74 Carles Marti
338 a7128ce1 Carles Marti
# Screening
339 a7128ce1 Carles Marti
340 8887f41d Carles
def get_screen_inp_file():
341 8887f41d Carles
    screen_inp_file = dos_inp.get('Screening', 'screen_inp_file')
342 8887f41d Carles
    if not os.path.isfile(screen_inp_file):
343 695dcff8 Carles Marti
        logger.error(f'File {screen_inp_file} not found.')
344 8887f41d Carles
        raise FileNotFoundError(f'File {screen_inp_file} not found')
345 8887f41d Carles
    return screen_inp_file
346 8887f41d Carles
347 8887f41d Carles
348 a765b11c Carles Marti
def get_surf_file():
349 a765b11c Carles Marti
    surf_file = dos_inp.get('Screening', 'surf_file')
350 a765b11c Carles Marti
    if not os.path.isfile(surf_file):
351 695dcff8 Carles Marti
        logger.error(f'File {surf_file} not found.')
352 a765b11c Carles Marti
        raise FileNotFoundError(f'File {surf_file} not found')
353 a765b11c Carles Marti
    return surf_file
354 a765b11c Carles Marti
355 a765b11c Carles Marti
356 8887f41d Carles
def get_sites():
357 8887f41d Carles
    err_msg = 'The value of sites should be a list of atom numbers ' \
358 8887f41d Carles
              '(ie. positive integers) or groups of atom numbers ' \
359 8887f41d Carles
              'grouped by parentheses-like enclosers. \n' \
360 8887f41d Carles
              'eg. 128,(135 138;141) 87 {45, 68}'
361 8887f41d Carles
    # Convert the string into a list of lists
362 8887f41d Carles
    sites = try_command(str2lst,
363 8887f41d Carles
                        [(ValueError, err_msg), (AttributeError, err_msg)],
364 8887f41d Carles
                        dos_inp.get('Screening', 'sites'))
365 8887f41d Carles
    # Check all elements of the list (of lists) are positive integers
366 8887f41d Carles
    for site in sites:
367 8887f41d Carles
        if type(site) is list:
368 8887f41d Carles
            for atom in site:
369 8887f41d Carles
                if atom < 0:
370 8887f41d Carles
                    logger.error(err_msg)
371 8887f41d Carles
                    raise ValueError(err_msg)
372 8887f41d Carles
        elif type(site) is int:
373 8887f41d Carles
            if site < 0:
374 8887f41d Carles
                logger.error(err_msg)
375 8887f41d Carles
                raise ValueError(err_msg)
376 8887f41d Carles
        else:
377 8887f41d Carles
            logger.error(err_msg)
378 8887f41d Carles
            raise ValueError(err_msg)
379 8887f41d Carles
380 8887f41d Carles
    return sites
381 8887f41d Carles
382 8887f41d Carles
383 7dd94df7 Carles Marti
def get_surf_ctrs2():
384 7dd94df7 Carles Marti
    err_msg = 'The value of surf_ctrs2 should be a list of atom numbers ' \
385 7dd94df7 Carles Marti
              '(ie. positive integers) or groups of atom numbers ' \
386 7dd94df7 Carles Marti
              'grouped by parentheses-like enclosers. \n' \
387 7dd94df7 Carles Marti
              'eg. 128,(135 138;141) 87 {45, 68}'
388 7dd94df7 Carles Marti
    # Convert the string into a list of lists
389 7dd94df7 Carles Marti
    surf_ctrs2 = try_command(str2lst,
390 7dd94df7 Carles Marti
                             [(ValueError, err_msg), (AttributeError, err_msg)],
391 7dd94df7 Carles Marti
                             dos_inp.get('Screening', 'surf_ctrs2'))
392 7dd94df7 Carles Marti
    # Check all elements of the list (of lists) are positive integers
393 7dd94df7 Carles Marti
    for ctr in surf_ctrs2:
394 7dd94df7 Carles Marti
        if type(ctr) is list:
395 7dd94df7 Carles Marti
            for atom in ctr:
396 7dd94df7 Carles Marti
                if atom < 0:
397 7dd94df7 Carles Marti
                    logger.error(err_msg)
398 7dd94df7 Carles Marti
                    raise ValueError(err_msg)
399 7dd94df7 Carles Marti
        elif type(ctr) is int:
400 7dd94df7 Carles Marti
            if ctr < 0:
401 7dd94df7 Carles Marti
                logger.error(err_msg)
402 7dd94df7 Carles Marti
                raise ValueError(err_msg)
403 7dd94df7 Carles Marti
        else:
404 7dd94df7 Carles Marti
            logger.error(err_msg)
405 7dd94df7 Carles Marti
            raise ValueError(err_msg)
406 7dd94df7 Carles Marti
407 7dd94df7 Carles Marti
    return surf_ctrs2
408 7dd94df7 Carles Marti
409 7dd94df7 Carles Marti
410 7dd94df7 Carles Marti
def get_molec_ctrs():
411 7dd94df7 Carles Marti
    err_msg = 'The value of molec_ctrs should be a list of atom' \
412 8887f41d Carles
              ' numbers (ie. positive integers) or groups of atom ' \
413 8887f41d Carles
              'numbers enclosed by parentheses-like characters. \n' \
414 8887f41d Carles
              'eg. 128,(135 138;141) 87 {45, 68}'
415 8887f41d Carles
    # Convert the string into a list of lists
416 7dd94df7 Carles Marti
    molec_ctrs = try_command(str2lst,
417 7dd94df7 Carles Marti
                             [(ValueError, err_msg),
418 7dd94df7 Carles Marti
                              (AttributeError, err_msg)],
419 7dd94df7 Carles Marti
                             dos_inp.get('Screening', 'molec_ctrs'))
420 7dd94df7 Carles Marti
    # Check all elements of the list (of lists) are positive integers
421 7dd94df7 Carles Marti
    for ctr in molec_ctrs:
422 7dd94df7 Carles Marti
        if isinstance(ctr, list):
423 7dd94df7 Carles Marti
            for atom in ctr:
424 7dd94df7 Carles Marti
                if atom < 0:
425 7dd94df7 Carles Marti
                    logger.error(err_msg)
426 7dd94df7 Carles Marti
                    raise ValueError(err_msg)
427 7dd94df7 Carles Marti
        elif isinstance(ctr, int):
428 7dd94df7 Carles Marti
            if ctr < 0:
429 7dd94df7 Carles Marti
                logger.error(err_msg)
430 7dd94df7 Carles Marti
                raise ValueError(err_msg)
431 7dd94df7 Carles Marti
        else:
432 7dd94df7 Carles Marti
            logger.error(err_msg)
433 7dd94df7 Carles Marti
            raise ValueError(err_msg)
434 7dd94df7 Carles Marti
435 7dd94df7 Carles Marti
    return molec_ctrs
436 7dd94df7 Carles Marti
437 7dd94df7 Carles Marti
438 7dd94df7 Carles Marti
def get_molec_ctrs2():
439 7dd94df7 Carles Marti
    err_msg = 'The value of molec_ctrs2 should be a list of atom ' \
440 7dd94df7 Carles Marti
              'numbers (ie. positive integers) or groups of atom ' \
441 7dd94df7 Carles Marti
              'numbers enclosed by parentheses-like characters. \n' \
442 7dd94df7 Carles Marti
              'eg. 128,(135 138;141) 87 {45, 68}'
443 7dd94df7 Carles Marti
    # Convert the string into a list of lists
444 7dd94df7 Carles Marti
    molec_ctrs2 = try_command(str2lst, [(ValueError, err_msg),
445 7dd94df7 Carles Marti
                                        (AttributeError, err_msg)],
446 7dd94df7 Carles Marti
                              dos_inp.get('Screening', 'molec_ctrs2'))
447 7dd94df7 Carles Marti
448 8887f41d Carles
    # Check all elements of the list (of lists) are positive integers
449 7dd94df7 Carles Marti
    for ctr in molec_ctrs2:
450 c845c6f2 Carles Marti
        if isinstance(ctr, list):
451 8887f41d Carles
            for atom in ctr:
452 8887f41d Carles
                if atom < 0:
453 8887f41d Carles
                    logger.error(err_msg)
454 8887f41d Carles
                    raise ValueError(err_msg)
455 c845c6f2 Carles Marti
        elif isinstance(ctr, int):
456 8887f41d Carles
            if ctr < 0:
457 8887f41d Carles
                logger.error(err_msg)
458 8887f41d Carles
                raise ValueError(err_msg)
459 8887f41d Carles
        else:
460 8887f41d Carles
            logger.error(err_msg)
461 8887f41d Carles
            raise ValueError(err_msg)
462 8887f41d Carles
463 7dd94df7 Carles Marti
    return molec_ctrs2
464 8887f41d Carles
465 8887f41d Carles
466 7dd94df7 Carles Marti
def get_molec_ctrs3():
467 7dd94df7 Carles Marti
    err_msg = 'The value of molec_ctrs3 should be a list of atom ' \
468 c845c6f2 Carles Marti
              'numbers (ie. positive integers) or groups of atom ' \
469 c845c6f2 Carles Marti
              'numbers enclosed by parentheses-like characters. \n' \
470 c845c6f2 Carles Marti
              'eg. 128,(135 138;141) 87 {45, 68}'
471 c845c6f2 Carles Marti
    # Convert the string into a list of lists
472 7dd94df7 Carles Marti
    molec_ctrs3 = try_command(str2lst, [(ValueError, err_msg),
473 7dd94df7 Carles Marti
                                        (AttributeError, err_msg)],
474 7dd94df7 Carles Marti
                              dos_inp.get('Screening', 'molec_ctrs3'))
475 c845c6f2 Carles Marti
476 c845c6f2 Carles Marti
    # Check all elements of the list (of lists) are positive integers
477 7dd94df7 Carles Marti
    for ctr in molec_ctrs3:
478 c845c6f2 Carles Marti
        if isinstance(ctr, list):
479 c845c6f2 Carles Marti
            for atom in ctr:
480 c845c6f2 Carles Marti
                if atom < 0:
481 c845c6f2 Carles Marti
                    logger.error(err_msg)
482 c845c6f2 Carles Marti
                    raise ValueError(err_msg)
483 c845c6f2 Carles Marti
        elif isinstance(ctr, int):
484 c845c6f2 Carles Marti
            if ctr < 0:
485 c845c6f2 Carles Marti
                logger.error(err_msg)
486 c845c6f2 Carles Marti
                raise ValueError(err_msg)
487 c845c6f2 Carles Marti
        else:
488 c845c6f2 Carles Marti
            logger.error(err_msg)
489 c845c6f2 Carles Marti
            raise ValueError(err_msg)
490 c845c6f2 Carles Marti
491 7dd94df7 Carles Marti
    return molec_ctrs3
492 c845c6f2 Carles Marti
493 c845c6f2 Carles Marti
494 a98d4172 Carles Marti
def get_max_helic_angle():
495 a98d4172 Carles Marti
    err_msg = "'max_helic_angle' must be a positive number in degrees"
496 a98d4172 Carles Marti
    max_helic_angle = try_command(dos_inp.getfloat, [(ValueError, err_msg)],
497 a98d4172 Carles Marti
                                  'Screening', 'max_helic_angle',
498 a98d4172 Carles Marti
                                  fallback=180.0)
499 a98d4172 Carles Marti
    if max_helic_angle < 0:
500 a98d4172 Carles Marti
        logger.error(err_msg)
501 a98d4172 Carles Marti
        raise ValueError(err_msg)
502 a98d4172 Carles Marti
503 a98d4172 Carles Marti
    return max_helic_angle
504 a98d4172 Carles Marti
505 a98d4172 Carles Marti
506 8af49f6d Carles Marti
def get_select_magns():
507 8af49f6d Carles Marti
    select_magns_vals = ['energy', 'moi']
508 8af49f6d Carles Marti
    select_magns_str = dos_inp.get('Screening', 'select_magns',
509 af2bf62f Carles Marti
                                   fallback='energy')
510 8af49f6d Carles Marti
    select_magns_str.replace(',', ' ').replace(';', ' ')
511 8af49f6d Carles Marti
    select_magns = select_magns_str.split(' ')
512 8af49f6d Carles Marti
    select_magns = [m.lower() for m in select_magns]
513 8af49f6d Carles Marti
    for m in select_magns:
514 8af49f6d Carles Marti
        check_expect_val(m, select_magns_vals)
515 8af49f6d Carles Marti
    return select_magns
516 8af49f6d Carles Marti
517 8af49f6d Carles Marti
518 af2bf62f Carles Marti
def get_confs_per_magn():
519 af2bf62f Carles Marti
    err_msg = num_error % ('confs_per_magn', 'positive integer')
520 af2bf62f Carles Marti
    confs_per_magn = try_command(dos_inp.getint, [(ValueError, err_msg)],
521 af2bf62f Carles Marti
                                 'Screening', 'confs_per_magn', fallback=2)
522 af2bf62f Carles Marti
    if confs_per_magn <= 0:
523 af2bf62f Carles Marti
        logger.error(err_msg)
524 af2bf62f Carles Marti
        raise ValueError(err_msg)
525 af2bf62f Carles Marti
    return confs_per_magn
526 af2bf62f Carles Marti
527 af2bf62f Carles Marti
528 bc703cab Carles Marti
def get_pbc_cell():
529 bc703cab Carles Marti
    err = "'pbc_cell' must be either 3 vectors of size 3 or False"
530 bc703cab Carles Marti
    pbc_cell_str = dos_inp.get('Screening', 'pbc_cell', fallback="False")
531 bc703cab Carles Marti
    if pbc_cell_str.lower() in turn_false_answers:
532 bc703cab Carles Marti
        return False
533 bc703cab Carles Marti
    else:
534 bc703cab Carles Marti
        pbc_cell = np.array(try_command(str2lst, [(ValueError, err)],
535 bc703cab Carles Marti
                                        pbc_cell_str, float))
536 bc703cab Carles Marti
        if pbc_cell.shape != (3, 3):
537 bc703cab Carles Marti
            logger.error(err)
538 bc703cab Carles Marti
            raise ValueError(err)
539 bc703cab Carles Marti
        return pbc_cell
540 bc703cab Carles Marti
541 bc703cab Carles Marti
542 c845c6f2 Carles Marti
def get_surf_norm_vect():
543 c845c6f2 Carles Marti
    err = "'surf_norm_vect' must be either a 3 component vector or 'x', 'y' " \
544 c845c6f2 Carles Marti
          "or 'z'"
545 9c16a7e2 Carles Marti
    cart_axes = {'x': [1.0, 0.0, 0.0], '-x': [-1.0, 0.0, 0.0],
546 9c16a7e2 Carles Marti
                 'y': [0.0, 1.0, 0.0], '-y': [0.0, -1.0, 0.0],
547 9c16a7e2 Carles Marti
                 'z': [0.0, 0.0, 1.0], '-z': [0.0, 0.0, -1.0]}
548 c845c6f2 Carles Marti
    surf_norm_vect_str = dos_inp.get('Screening', 'surf_norm_vect',
549 5fb01677 Carles Marti
                                     fallback="z")
550 3d56e566 Carles Marti
551 9c16a7e2 Carles Marti
    if surf_norm_vect_str in cart_axes:
552 9c16a7e2 Carles Marti
        surf_norm_vect = cart_axes[surf_norm_vect_str]
553 3d56e566 Carles Marti
    else:
554 3d56e566 Carles Marti
        surf_norm_vect = try_command(str2lst, [(ValueError, err)],
555 5fb01677 Carles Marti
                                     surf_norm_vect_str, float)
556 c845c6f2 Carles Marti
        if len(surf_norm_vect) != 3:
557 c845c6f2 Carles Marti
            logger.error(err)
558 c845c6f2 Carles Marti
            raise ValueError(err)
559 3d56e566 Carles Marti
560 cea7af64 Carles Marti
    return np.array(surf_norm_vect)/np.linalg.norm(surf_norm_vect)
561 c845c6f2 Carles Marti
562 c845c6f2 Carles Marti
563 7dd94df7 Carles Marti
def get_set_angles():
564 7dd94df7 Carles Marti
    set_vals = ['euler', 'chemcat']
565 7dd94df7 Carles Marti
    check_expect_val(dos_inp.get('Screening', 'set_angles').lower(), set_vals)
566 5261a07f Carles Marti
    set_angles = dos_inp.get('Screening', 'set_angles',
567 5261a07f Carles Marti
                             fallback='euler').lower()
568 7dd94df7 Carles Marti
    return set_angles
569 a7c7b43e Carles Marti
570 a7c7b43e Carles Marti
571 8887f41d Carles
def get_pts_per_angle():
572 d4bedc18 Carles Marti
    err_msg = num_error % ('sample_points_per_angle', 'positive integer')
573 8887f41d Carles
    pts_per_angle = try_command(dos_inp.getint,
574 8887f41d Carles
                                [(ValueError, err_msg)],
575 8887f41d Carles
                                'Screening', 'sample_points_per_angle',
576 8887f41d Carles
                                fallback=3)
577 d4bedc18 Carles Marti
    if pts_per_angle <= 0:
578 d4bedc18 Carles Marti
        logger.error(err_msg)
579 d4bedc18 Carles Marti
        raise ValueError(err_msg)
580 8887f41d Carles
    return pts_per_angle
581 8887f41d Carles
582 8887f41d Carles
583 7d97341d Carles Marti
def get_max_structures():
584 7d97341d Carles Marti
    err_msg = num_error % ('max_structures', 'positive integer')
585 21209d96 Carles Marti
    max_structs = dos_inp.get('Screening', 'max_structures', fallback="False")
586 21209d96 Carles Marti
    if max_structs.lower() in turn_false_answers:
587 21209d96 Carles Marti
        return np.inf
588 21209d96 Carles Marti
    if try_command(int, [(ValueError, err_msg)], max_structs) <= 0:
589 7d97341d Carles Marti
        logger.error(err_msg)
590 7d97341d Carles Marti
        raise ValueError(err_msg)
591 21209d96 Carles Marti
    return int(max_structs)
592 7d97341d Carles Marti
593 7d97341d Carles Marti
594 8887f41d Carles
def get_coll_thrsld():
595 8887f41d Carles
    err_msg = num_error % ('collision_threshold',
596 8887f41d Carles
                           'positive decimal number')
597 8887f41d Carles
598 8887f41d Carles
    coll_thrsld = try_command(dos_inp.getfloat,
599 8887f41d Carles
                              [(ValueError, err_msg)],
600 8887f41d Carles
                              'Screening', 'collision_threshold', fallback=1.2)
601 8887f41d Carles
    if coll_thrsld <= 0:
602 8887f41d Carles
        logger.error(err_msg)
603 8887f41d Carles
        raise ValueError(err_msg)
604 8887f41d Carles
605 8887f41d Carles
    return coll_thrsld
606 8887f41d Carles
607 8887f41d Carles
608 8887f41d Carles
def get_screen_rmsd():
609 8887f41d Carles
    err_msg = num_error % ('screen_rmsd', 'positive decimal number')
610 8887f41d Carles
    screen_rmsd = try_command(dos_inp.getfloat,
611 8887f41d Carles
                              [(ValueError, err_msg)],
612 8887f41d Carles
                              'Screening', 'screen_rmsd', fallback=0.05)
613 8887f41d Carles
    if screen_rmsd <= 0:
614 8887f41d Carles
        logger.error(err_msg)
615 8887f41d Carles
        raise ValueError(err_msg)
616 8887f41d Carles
617 8887f41d Carles
    return screen_rmsd
618 8887f41d Carles
619 8887f41d Carles
620 5fb01677 Carles Marti
def get_min_coll_height():
621 5fb01677 Carles Marti
    err_msg = num_error % ('min_coll_height', 'decimal number')
622 5fb01677 Carles Marti
    min_coll_height = dos_inp.get('Screening', 'min_coll_height',
623 5fb01677 Carles Marti
                                  fallback="False")
624 5fb01677 Carles Marti
    if min_coll_height.lower() in turn_false_answers:
625 5fb01677 Carles Marti
        min_coll_height = False
626 8887f41d Carles
    else:
627 5fb01677 Carles Marti
        min_coll_height = try_command(float, [(ValueError, err_msg)],
628 5fb01677 Carles Marti
                                      min_coll_height)
629 8887f41d Carles
630 5fb01677 Carles Marti
    return min_coll_height
631 8887f41d Carles
632 8887f41d Carles
633 c25aa299 Carles Marti
def get_H_donor(spec_atoms):
634 c25aa299 Carles Marti
    from ase.data import chemical_symbols
635 c25aa299 Carles Marti
    err_msg = "The value of 'h_donor' must be either False, a chemical symbol "\
636 c25aa299 Carles Marti
              "or an atom index"
637 c25aa299 Carles Marti
    h_donor_str = dos_inp.get('Screening', 'h_donor', fallback="False")
638 c25aa299 Carles Marti
    h_donor = []
639 c25aa299 Carles Marti
    if h_donor_str.lower() in turn_false_answers:
640 c25aa299 Carles Marti
        return False
641 c25aa299 Carles Marti
    err = False
642 c25aa299 Carles Marti
    for el in h_donor_str.split():
643 c25aa299 Carles Marti
        try:
644 c25aa299 Carles Marti
            h_donor.append(int(el))
645 c25aa299 Carles Marti
        except ValueError:
646 c25aa299 Carles Marti
            if el not in chemical_symbols + [nw_sym for pairs in spec_atoms
647 c25aa299 Carles Marti
                                             for nw_sym in pairs]:
648 c25aa299 Carles Marti
                err = True
649 c25aa299 Carles Marti
            else:
650 c25aa299 Carles Marti
                h_donor.append(el)
651 c25aa299 Carles Marti
        finally:
652 c25aa299 Carles Marti
            if err:
653 c25aa299 Carles Marti
                logger.error(err_msg)
654 c25aa299 Carles Marti
                ValueError(err_msg)
655 c25aa299 Carles Marti
    return h_donor
656 c25aa299 Carles Marti
657 c25aa299 Carles Marti
658 c25aa299 Carles Marti
def get_H_acceptor(spec_atoms):
659 c25aa299 Carles Marti
    from ase.data import chemical_symbols
660 c25aa299 Carles Marti
    err_msg = "The value of 'h_acceptor' must be either 'all', a chemical " \
661 c25aa299 Carles Marti
              "symbol or an atom index"
662 c25aa299 Carles Marti
    h_acceptor_str = dos_inp.get('Screening', 'h_acceptor', fallback="all")
663 c25aa299 Carles Marti
    if h_acceptor_str.lower() == "all":
664 c25aa299 Carles Marti
        return "all"
665 c25aa299 Carles Marti
    h_acceptor = []
666 c25aa299 Carles Marti
    err = False
667 c25aa299 Carles Marti
    for el in h_acceptor_str.split():
668 c25aa299 Carles Marti
        try:
669 c25aa299 Carles Marti
            h_acceptor.append(int(el))
670 c25aa299 Carles Marti
        except ValueError:
671 c25aa299 Carles Marti
            if el not in chemical_symbols + [nw_sym for pairs in spec_atoms
672 c25aa299 Carles Marti
                                             for nw_sym in pairs]:
673 c25aa299 Carles Marti
                err = True
674 c25aa299 Carles Marti
            else:
675 c25aa299 Carles Marti
                h_acceptor.append(el)
676 c25aa299 Carles Marti
        finally:
677 c25aa299 Carles Marti
            if err:
678 c25aa299 Carles Marti
                logger.error(err_msg)
679 c25aa299 Carles Marti
                ValueError(err_msg)
680 c25aa299 Carles Marti
    return h_acceptor
681 a765b11c Carles Marti
682 a765b11c Carles Marti
683 a7128ce1 Carles Marti
# Refinement
684 a7128ce1 Carles Marti
685 a7128ce1 Carles Marti
def get_refine_inp_file():  # TODO if not specified try isol_inp_file.
686 8887f41d Carles
    refine_inp_file = dos_inp.get('Refinement', 'refine_inp_file')
687 8887f41d Carles
    if not os.path.isfile(refine_inp_file):
688 695dcff8 Carles Marti
        logger.error(f'File {refine_inp_file} not found.')
689 8887f41d Carles
        raise FileNotFoundError(f'File {refine_inp_file} not found')
690 8887f41d Carles
691 8887f41d Carles
    return refine_inp_file
692 8887f41d Carles
693 8887f41d Carles
694 8887f41d Carles
def get_energy_cutoff():
695 8887f41d Carles
    err_msg = num_error % ('energy_cutoff', 'positive decimal number')
696 8887f41d Carles
    energy_cutoff = try_command(dos_inp.getfloat,
697 8887f41d Carles
                                [(ValueError, err_msg)],
698 8887f41d Carles
                                'Refinement', 'energy_cutoff', fallback=0.5)
699 8887f41d Carles
    if energy_cutoff < 0:
700 8887f41d Carles
        logger.error(err_msg)
701 8887f41d Carles
        raise ValueError(err_msg)
702 8887f41d Carles
    return energy_cutoff
703 8887f41d Carles
704 8887f41d Carles
705 c25aa299 Carles Marti
# Read input parameters
706 c25aa299 Carles Marti
707 8887f41d Carles
def read_input(in_file):
708 8887f41d Carles
    err = False
709 8887f41d Carles
    try:
710 8887f41d Carles
        dos_inp.read(in_file)
711 8887f41d Carles
    except MissingSectionHeaderError as e:
712 8887f41d Carles
        logger.error('There are options in the input file without a Section '
713 695dcff8 Carles Marti
                     'header.')
714 8887f41d Carles
        err = e
715 8887f41d Carles
    except DuplicateOptionError as e:
716 8887f41d Carles
        logger.error('There is an option in the input file that has been '
717 0bca5abb Carles Marti
                     'specified more than once.')
718 8887f41d Carles
        err = e
719 8887f41d Carles
    except Exception as e:
720 8887f41d Carles
        err = e
721 8887f41d Carles
    else:
722 8887f41d Carles
        err = False
723 8887f41d Carles
    finally:
724 8887f41d Carles
        if isinstance(err, BaseException):
725 8887f41d Carles
            raise err
726 17e72a49 Carles
727 7dd94df7 Carles Marti
    inp_vars = {}
728 8887f41d Carles
729 8887f41d Carles
    # Global
730 8887f41d Carles
    if not dos_inp.has_section('Global'):
731 8887f41d Carles
        logger.error(no_sect_err % 'Global')
732 8887f41d Carles
        raise NoSectionError('Global')
733 8887f41d Carles
734 8887f41d Carles
    # Mandatory options
735 8887f41d Carles
    # Checks whether the mandatory options 'run_type', 'code', etc. are present.
736 821dca42 Carles Marti
    glob_mand_opts = ['run_type', 'batch_q_sys']
737 7fd58762 Carles
    for opt in glob_mand_opts:
738 8887f41d Carles
        if not dos_inp.has_option('Global', opt):
739 8887f41d Carles
            logger.error(no_opt_err % (opt, 'Global'))
740 8887f41d Carles
            raise NoOptionError(opt, 'Global')
741 8887f41d Carles
742 8887f41d Carles
    # Gets which sections are to be carried out
743 8887f41d Carles
    isolated, screening, refinement = get_run_type()
744 7dd94df7 Carles Marti
    inp_vars['isolated'] = isolated
745 7dd94df7 Carles Marti
    inp_vars['screening'] = screening
746 7dd94df7 Carles Marti
    inp_vars['refinement'] = refinement
747 7dd94df7 Carles Marti
    inp_vars['batch_q_sys'] = get_batch_q_sys()
748 8887f41d Carles
749 99afde40 Carles
    # Dependent options:
750 7dd94df7 Carles Marti
    inp_vars['code'] = get_code()
751 7dd94df7 Carles Marti
    if inp_vars['batch_q_sys']:
752 7dd94df7 Carles Marti
        inp_vars['type_max'] = get_type_max()
753 7dd94df7 Carles Marti
        inp_vars['max_jobs'] = get_max_jobs()
754 7dd94df7 Carles Marti
        if inp_vars['batch_q_sys'] != 'local':
755 09c3325a Carles Marti
            if not dos_inp.has_option('Global', 'subm_script'):
756 09c3325a Carles Marti
                logger.error(no_opt_err % ('subm_script', 'Global'))
757 09c3325a Carles Marti
                raise NoOptionError('subm_script', 'Global')
758 7dd94df7 Carles Marti
            inp_vars['subm_script'] = get_subm_script()
759 7dd94df7 Carles Marti
        elif inp_vars['type_max'] == "p":
760 09c3325a Carles Marti
            err = "'type_max' cannot be set to 'pending'/'queued' when " \
761 09c3325a Carles Marti
                  "'batch_q_sys' is set to 'local' "
762 09c3325a Carles Marti
            logger.error(err)
763 09c3325a Carles Marti
            raise ValueError(err)
764 99afde40 Carles
765 8887f41d Carles
    # Facultative options (Default/Fallback value present)
766 7dd94df7 Carles Marti
    inp_vars['project_name'] = get_project_name()
767 7dd94df7 Carles Marti
    inp_vars['relaunch_err'] = get_relaunch_err()
768 7dd94df7 Carles Marti
    inp_vars['special_atoms'] = get_special_atoms()
769 8887f41d Carles
770 8887f41d Carles
    # Isolated
771 b1d27be5 Carles
    if isolated:
772 b606c71a Carles
        if not dos_inp.has_section('Isolated'):
773 b606c71a Carles
            logger.error(no_sect_err % 'Isolated')
774 b606c71a Carles
            raise NoSectionError('Isolated')
775 8887f41d Carles
        # Mandatory options
776 8887f41d Carles
        # Checks whether the mandatory options are present.
777 95dc2c8e Carles
        iso_mand_opts = ['isol_inp_file', 'molec_file']
778 8887f41d Carles
        for opt in iso_mand_opts:
779 8887f41d Carles
            if not dos_inp.has_option('Isolated', opt):
780 8887f41d Carles
                logger.error(no_opt_err % (opt, 'Isolated'))
781 8887f41d Carles
                raise NoOptionError(opt, 'Isolated')
782 7dd94df7 Carles Marti
        inp_vars['isol_inp_file'] = get_isol_inp_file()
783 7dd94df7 Carles Marti
        if 'code ' in inp_vars:
784 7dd94df7 Carles Marti
            check_inp_file(inp_vars['isol_inp_file'], inp_vars['code'])
785 7dd94df7 Carles Marti
        inp_vars['molec_file'] = get_molec_file()
786 8887f41d Carles
787 8887f41d Carles
        # Facultative options (Default/Fallback value present)
788 7dd94df7 Carles Marti
        inp_vars['num_conformers'] = get_num_conformers()
789 7dd94df7 Carles Marti
        # inp_vars['num_prom_cand'] = get_num_prom_cand()
790 7dd94df7 Carles Marti
        # inp_vars['iso_rmsd'] = get_iso_rmsd()
791 7dd94df7 Carles Marti
        inp_vars['pre_opt'] = get_pre_opt()
792 8887f41d Carles
793 8887f41d Carles
    # Screening
794 b1d27be5 Carles
    if screening:
795 772b40e5 Carles
        if not dos_inp.has_section('Screening'):
796 9f7bb440 Carles
            logger.error(no_sect_err % 'Screening')
797 772b40e5 Carles
            raise NoSectionError('Screening')
798 8887f41d Carles
        # Mandatory options:
799 8887f41d Carles
        # Checks whether the mandatory options are present.
800 a765b11c Carles Marti
        screen_mand_opts = ['screen_inp_file', 'surf_file', 'sites',
801 7dd94df7 Carles Marti
                            'molec_ctrs']
802 8887f41d Carles
        for opt in screen_mand_opts:
803 772b40e5 Carles
            if not dos_inp.has_option('Screening', opt):
804 9f7bb440 Carles
                logger.error(no_opt_err % (opt, 'Screening'))
805 b1d27be5 Carles
                raise NoOptionError(opt, 'Screening')
806 7dd94df7 Carles Marti
        inp_vars['screen_inp_file'] = get_screen_inp_file()
807 7dd94df7 Carles Marti
        inp_vars['surf_file'] = get_surf_file()
808 7dd94df7 Carles Marti
        inp_vars['sites'] = get_sites()
809 7dd94df7 Carles Marti
        inp_vars['molec_ctrs'] = get_molec_ctrs()
810 8887f41d Carles
811 8887f41d Carles
        # Facultative options (Default value present)
812 7dd94df7 Carles Marti
        inp_vars['select_magns'] = get_select_magns()
813 7dd94df7 Carles Marti
        inp_vars['confs_per_magn'] = get_confs_per_magn()
814 7dd94df7 Carles Marti
        inp_vars['surf_norm_vect'] = get_surf_norm_vect()
815 7dd94df7 Carles Marti
        inp_vars['set_angles'] = get_set_angles()
816 7dd94df7 Carles Marti
        inp_vars['sample_points_per_angle'] = get_pts_per_angle()
817 c25aa299 Carles Marti
        inp_vars['pbc_cell'] = get_pbc_cell()
818 7dd94df7 Carles Marti
        inp_vars['collision_threshold'] = get_coll_thrsld()
819 7dd94df7 Carles Marti
        inp_vars['min_coll_height'] = get_min_coll_height()
820 c25aa299 Carles Marti
        inp_vars['h_donor'] = get_H_donor(inp_vars['special_atoms'])
821 c25aa299 Carles Marti
        inp_vars['max_structures'] = get_max_structures()
822 8887f41d Carles
823 7dd94df7 Carles Marti
        if inp_vars['set_angles'] == "chemcat":
824 a98d4172 Carles Marti
            chemcat_opts = ['molec_ctrs2', 'molec_ctrs3', 'surf_ctrs2',
825 a98d4172 Carles Marti
                            'max_helic_angle']
826 7dd94df7 Carles Marti
            for opt in chemcat_opts:
827 7dd94df7 Carles Marti
                if not dos_inp.has_option('Screening', opt):
828 7dd94df7 Carles Marti
                    logger.error(no_opt_err % (opt, 'Screening'))
829 7dd94df7 Carles Marti
                    raise NoOptionError(opt, 'Screening')
830 a98d4172 Carles Marti
            inp_vars['max_helic_angle'] = get_max_helic_angle()
831 7dd94df7 Carles Marti
            inp_vars['molec_ctrs2'] = get_molec_ctrs2()
832 7dd94df7 Carles Marti
            inp_vars['molec_ctrs3'] = get_molec_ctrs3()
833 7dd94df7 Carles Marti
            inp_vars['surf_ctrs2'] = get_surf_ctrs2()
834 7dd94df7 Carles Marti
            if len(inp_vars["molec_ctrs2"]) != len(inp_vars['molec_ctrs']) \
835 7dd94df7 Carles Marti
                    or len(inp_vars["molec_ctrs3"]) != \
836 7dd94df7 Carles Marti
                    len(inp_vars['molec_ctrs']) \
837 7dd94df7 Carles Marti
                    or len(inp_vars['surf_ctrs2']) != len(inp_vars['sites']):
838 c25aa299 Carles Marti
                err = "'molec_ctrs' 'molec_ctrs2' and 'molec_ctrs2' must have " \
839 c25aa299 Carles Marti
                      "the same number of indices "
840 7dd94df7 Carles Marti
                logger.error(err)
841 7dd94df7 Carles Marti
                raise ValueError(err)
842 7dd94df7 Carles Marti
843 c25aa299 Carles Marti
        cart_axes = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0],
844 c25aa299 Carles Marti
                     [-1.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, -1.0]]
845 c25aa299 Carles Marti
        if inp_vars['min_coll_height'] is not False \
846 c25aa299 Carles Marti
                and inp_vars['surf_norm_vect'].tolist() not in cart_axes:
847 c25aa299 Carles Marti
            logger.warning("'min_coll_height' option is only implemented for "
848 c25aa299 Carles Marti
                           "'surf_norm_vect' to be one of the x, y or z axes.")
849 c25aa299 Carles Marti
850 c25aa299 Carles Marti
        if inp_vars['h_donor'] is False:
851 c25aa299 Carles Marti
            inp_vars['h_acceptor'] = False
852 c25aa299 Carles Marti
        else:
853 c25aa299 Carles Marti
            inp_vars['h_acceptor'] = get_H_acceptor(inp_vars['special_atoms'])
854 c25aa299 Carles Marti
855 8887f41d Carles
    # Refinement
856 b1d27be5 Carles
    if refinement:
857 8887f41d Carles
        if not dos_inp.has_section('Refinement'):
858 8887f41d Carles
            logger.error(no_sect_err % 'Refinement')
859 8887f41d Carles
            raise NoSectionError('Refinement')
860 8887f41d Carles
        # Mandatory options
861 8887f41d Carles
        # Checks whether the mandatory options are present.
862 8887f41d Carles
        ref_mand_opts = ['refine_inp_file']
863 8887f41d Carles
        for opt in ref_mand_opts:
864 8887f41d Carles
            if not dos_inp.has_option('Refinement', opt):
865 8887f41d Carles
                logger.error(no_opt_err % (opt, 'Refinement'))
866 8887f41d Carles
                raise NoOptionError(opt, 'Refinement')
867 7dd94df7 Carles Marti
        inp_vars['refine_inp_file'] = get_refine_inp_file()
868 8887f41d Carles
869 8887f41d Carles
        # Facultative options (Default value present)
870 7dd94df7 Carles Marti
        inp_vars['energy_cutoff'] = get_energy_cutoff()
871 b1d27be5 Carles
        # end energy_cutoff
872 9f7bb440 Carles
873 a5cc42ff Carles Marti
    return_vars_str = "\n\t".join([str(key) + ": " + str(value)
874 7dd94df7 Carles Marti
                                   for key, value in inp_vars.items()])
875 d8a6314e Carles
    logger.info(
876 62a87644 Carles Marti
        f'Correctly read {in_file} parameters: \n\n\t{return_vars_str}\n')
877 d8a6314e Carles
878 7dd94df7 Carles Marti
    return inp_vars
879 8887f41d Carles
880 8887f41d Carles
881 8887f41d Carles
if __name__ == "__main__":
882 8887f41d Carles
    import sys
883 8887f41d Carles
884 8887f41d Carles
    print(read_input(sys.argv[1]))