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

dockonsurf / modules / dos_input.py @ 5261a07f

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