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

dockonsurf / modules / dos_input.py @ 9fd1daa6

Historique | Voir | Annoter | Télécharger (23,58 ko)

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

3
Functions
4
try_command:Tries to run a command and logs its exceptions (expected and not).
5
str2lst: Converts a string of integers, and groups of them, to a list of lists.
6
check_expect_val: Checks whether the value of an option has an adequate value.
7
read_input: Sets up the calculation by reading the parameters from input file.
8
get_run_type: Gets 'run_type' value and checks that its value is acceptable.
9
get_code: Gets 'code' value and checks that its value is acceptable.
10
get_batch_q_sys: Gets 'batch_q_sys' value and checks that its value is
11
acceptable.
12
get_relaunch_err: Gets 'relaunch_err' value and checks that its value is
13
acceptable.
14
get_max_qw: Gets 'max_qw' value and checks that its value is acceptable.
15
get_special_atoms: Gets 'special_atoms' value and checks that its value is
16
acceptable.
17
get_isol_inp_file: Gets 'isol_inp_file' value and checks that its value is
18
acceptable.
19
get_cluster_magns: Gets 'cluster_magns' value and checks that its value is
20
acceptable.
21
get_num_conformers: Gets 'num_conformers' value and checks that its value is
22
acceptable.
23
get_num_prom_cand: Gets 'num_prom_cand' value and checks that its value is
24
acceptable.
25
get_iso_rmsd: Gets 'iso_rmsd' value and checks that its value is acceptable.
26
get_min_confs: Gets 'min_confs' value and checks that its value is acceptable.
27
get_screen_inp_file: Gets 'screen_inp_file' value and checks that its value is
28
acceptable.
29
get_sites: Gets 'sites' value and checks that its value is acceptable.
30
get_molec_ads_ctrs: Gets 'molec_ads_ctrs' value and checks that its value is
31
acceptable.
32
get_try_disso: Gets 'try_disso' value and checks that its value is acceptable.
33
get_pts_per_angle: Gets 'pts_per_angle' value and checks that its value is
34
acceptable.
35
get_coll_thrsld: Gets 'coll_thrsld' value and checks that its value is
36
acceptable.
37
get_screen_rmsd: Gets 'screen_rmsd' value and checks that its value is
38
acceptable.
39
get_coll_bottom_z: Gets 'coll_bottom_z' value and checks that its value is
40
acceptable.
41
get_refine_inp_file: Gets 'refine_inp_file' value and checks that its value is
42
acceptable.
43
get_energy_cutoff: Gets 'energy_cutoff' value and checks that its value is
44
acceptable.
45
"""
46
import os.path
47
import logging
48
from configparser import ConfigParser, NoSectionError, NoOptionError, \
49
    MissingSectionHeaderError, DuplicateOptionError
50

    
51
logger = logging.getLogger('DockOnSurf')
52

    
53
dos_inp = ConfigParser(inline_comment_prefixes='#',
54
                       empty_lines_in_values=False)
55

    
56
new_answers = {'n': False, 'none': False, 'nay': False,
57
               'y': True, '': True, 'aye': True, 'sure': True}
58
for answer, val in new_answers.items():
59
    dos_inp.BOOLEAN_STATES[answer] = val
60
turn_false_answers = [answer for answer in dos_inp.BOOLEAN_STATES
61
                      if dos_inp.BOOLEAN_STATES[answer] is False]
62

    
63
no_sect_err = "Section '%s' not found on input file"
64
no_opt_err = "Option '%s' not found on section '%s'"
65
num_error = "'%s' value must be a %s"
66
unexp_error = "An unexpected error occurred"
67

    
68

    
69
def try_command(command, expct_error_types: list, *args, **kwargs):
70
    """Try to run a command and record exceptions (expected and not) on a log.
71
    
72
    @param command: method or function, the command to be executed.
73
    @param expct_error_types: tuple of tuples, every inner tuple is supposed to
74
    contain an exception type (eg. ValueError, TypeError, etc.) to be caught and
75
    a message to print in the log and on the screen explaining the exception.
76
    Error types that are not allow to be called with a custom message as only
77
    error argument are not supported.
78
    The outer tuple encloses all couples of error types and their relative
79
    messages.
80
    *args and **kwargs: arguments and keyword-arguments of the command to be
81
    executed.
82
    When trying to run 'command' with its args and kwargs, if an exception
83
    present on the 'error_types' occurs, its relative error message is recorded
84
    on the log and a same type exception is raised with the custom message.
85
    """
86

    
87
    err = False
88
    try:
89
        return_val = command(*args, **kwargs)
90
    except Exception as e:
91
        for expct_err in expct_error_types:
92
            if isinstance(e, expct_err[0]):
93
                logger.error(expct_err[1])
94
                err = expct_err[0](expct_err[1])
95
                break
96
        else:
97
            logger.exception(unexp_error)
98
            err = e
99
    else:
100
        err = False
101
        return return_val
102
    finally:
103
        if isinstance(err, BaseException):
104
            raise err
105

    
106

    
107
def str2lst(cmplx_str):  # TODO: enable deeper level of nested lists
108
    """Converts a string of integers, and groups of them, to a list.
109

110
    Keyword arguments:
111
    @param cmplx_str: str, string of integers and groups of them enclosed by
112
    parentheses-like characters.
113
    - Group enclosers: '()' '[]' and '{}'.
114
    - Integer separators: ',' ';' and ' '.
115
    - Nested groups are not allowed: '3 ((6 7) 8) 4'.
116

117
    @return list, list of integers, or list of integers in the case they were
118
    grouped. First, the singlets are placed, and then the groups in input order.
119

120
    eg. '128,(135 138;141] 87 {45, 68}' -> [128, 87, [135, 138, 141], [45, 68]]
121
    """
122

    
123
    # Checks
124
    error_msg = "Function argument should be a str,sequence of integer " \
125
                "numbers separated by ',' ';' or ' '." \
126
                "\nThey can be grouped in parentheses-like enclosers: '()', " \
127
                "'[]' or {}. Nested groups are not allowed. \n" \
128
                "eg. 128,(135 138;141) 87 {45, 68}"
129
    cmplx_str = try_command(cmplx_str.replace, [(AttributeError, error_msg)],
130
                            ',', ' ')
131

    
132
    cmplx_str = cmplx_str.replace(';', ' ').replace('[', '(').replace(
133
        ']', ')').replace('{', '(').replace('}', ')')
134

    
135
    try_command(list, [(ValueError, error_msg)], map(int, cmplx_str.replace(
136
        ')', '').replace('(', '').split()))
137

    
138
    deepness = 0
139
    for el in cmplx_str.split():
140
        if '(' in el:
141
            deepness += 1
142
        if ')' in el:
143
            deepness += -1
144
        if deepness > 1 or deepness < 0:
145
            logger.error(error_msg)
146
            raise ValueError(error_msg)
147

    
148
    init_list = cmplx_str.split()
149
    start_group = []
150
    end_group = []
151
    for i, element in enumerate(init_list):
152
        if '(' in element:
153
            start_group.append(i)
154
            init_list[i] = element.replace('(', '')
155
        if ')' in element:
156
            end_group.append(i)
157
            init_list[i] = element.replace(')', '')
158

    
159
    init_list = list(map(int, init_list))
160

    
161
    new_list = []
162
    for start_el, end_el in zip(start_group, end_group):
163
        new_list.append(init_list[start_el:end_el + 1])
164

    
165
    for v in new_list:
166
        for el in v:
167
            init_list.remove(el)
168
    return init_list + new_list
169

    
170

    
171
def check_expect_val(value, expect_vals):
172
    """Checks whether an option lies within its expected values.
173

174
    Keyword arguments:
175
    @param value: The variable to check if its value lies within the expected
176
    ones
177
    @param expect_vals: list, list of values allowed for the present option.
178
    @raise ValueError: if the value is not among the expected ones.
179
    @return True if the value is among the expected ones.
180
    """
181
    adeq_val_err = "'%s' is not an adequate value.\n" \
182
                   "Adequate values: %s"
183
    if not any([exp_val in value for exp_val in expect_vals]):
184
        logger.error(adeq_val_err % (value, expect_vals))
185
        raise ValueError(adeq_val_err % (value, expect_vals))
186

    
187
    return True
188

    
189

    
190
def get_run_type():
191
    isolated, screening, refinement = (False, False, False)
192
    run_type_vals = ['isolated', 'screening', 'refinement', 'adsorption',
193
                     'full']
194
    check_expect_val(dos_inp.get('Global', 'run_type').lower(), run_type_vals)
195

    
196
    run_type = dos_inp.get('Global', 'run_type').lower()
197
    if 'isolated' in run_type:
198
        isolated = True
199
    if 'screening' in run_type:
200
        screening = True
201
    if 'refinement' in run_type:
202
        refinement = True
203
    if 'adsorption' in run_type:
204
        screening, refinement = (True, True)
205
    if 'full' in run_type:
206
        isolated, screening, refinement = (True, True, True)
207

    
208
    return isolated, screening, refinement
209

    
210

    
211
def get_code():
212
    code_vals = ['cp2k']
213
    check_expect_val(dos_inp.get('Global', 'code').lower(), code_vals)
214
    code = dos_inp.get('Global', 'code').lower()
215
    return code
216

    
217

    
218
def get_batch_q_sys():
219
    batch_q_sys_vals = ['sge', 'local']
220
    check_expect_val(dos_inp.get('Global', 'batch_q_sys').lower(),
221
                     batch_q_sys_vals)
222
    batch_q_sys = dos_inp.get('Global', 'batch_q_sys').lower()
223
    return batch_q_sys
224

    
225

    
226
def get_subm_script():
227
    subm_script = dos_inp.get('Global', 'subm_script', fallback=False)
228
    if subm_script and not os.path.isfile(subm_script):
229
        logger.error(f'File {subm_script} not found')
230
        raise FileNotFoundError(f'File {subm_script} not found')
231
    return subm_script
232

    
233

    
234
def get_project_name():
235
    project_name = dos_inp.get('Global', 'project_name')
236
    return project_name
237

    
238

    
239
def get_relaunch_err():
240
    relaunch_err_vals = ['geo_not_conv', 'false']
241
    relaunch_err = dos_inp.get('Global', 'relaunch_err',
242
                               fallback="False")
243
    if relaunch_err.lower() in turn_false_answers:
244
        return False
245
    else:
246
        check_expect_val(relaunch_err.lower(), relaunch_err_vals)
247
    return relaunch_err
248

    
249

    
250
def get_max_qw():
251
    err_msg = num_error % ('max_qw', 'positive integer')
252
    max_qw = try_command(dos_inp.getint, [(ValueError, err_msg)],
253
                         'Global', 'max_qw', fallback=3)
254

    
255
    if max_qw < 1:
256
        logger.error(num_error % ('max_qw', 'positive integer'))
257
        raise ValueError(num_error % ('max_qw', 'positive integer'))
258
    return max_qw
259

    
260

    
261
def get_special_atoms():
262
    from ase.data import chemical_symbols
263

    
264
    spec_at_err = '\'special_atoms\' does not have an adequate format.\n' \
265
                  'Adequate format: (Fe1 Fe) (O1 O)'
266
    special_atoms = dos_inp.get('Global', 'special_atoms', fallback="False")
267
    if special_atoms.lower() in turn_false_answers:
268
        special_atoms = False
269
    else:
270
        # Converts the string into a list of tuples
271
        lst_tple = [tuple(pair.replace("(", "").split()) for pair in
272
                    special_atoms.split(")")[:-1]]
273
        if len(lst_tple) == 0:
274
            logger.error(spec_at_err)
275
            raise ValueError(spec_at_err)
276
        for i, tup in enumerate(lst_tple):
277
            if type(tup) is not tuple or len(tup) != 2:
278
                logger.error(spec_at_err)
279
                raise ValueError(spec_at_err)
280
            if tup[1].capitalize() not in chemical_symbols:
281
                elem_err = "The second element of the couple should be an " \
282
                           "actual element of the periodic table"
283
                logger.error(elem_err)
284
                raise ValueError(elem_err)
285
            if tup[0].capitalize() in chemical_symbols:
286
                elem_err = "The first element of the couple is already an " \
287
                           "actual element of the periodic table, "
288
                logger.error(elem_err)
289
                raise ValueError(elem_err)
290
            for j, tup2 in enumerate(lst_tple):
291
                if j <= i:
292
                    continue
293
                if tup2[0] == tup[0]:
294
                    label_err = f'You have specified the label {tup[0]} to ' \
295
                                f'more than one special atom'
296
                    logger.error(label_err)
297
                    raise ValueError(label_err)
298
        special_atoms = lst_tple
299
    return special_atoms
300

    
301

    
302
def get_isol_inp_file():
303
    isol_inp_file = dos_inp.get('Isolated', 'isol_inp_file')
304
    if not os.path.isfile(isol_inp_file):
305
        logger.error(f'File {isol_inp_file} not found')
306
        raise FileNotFoundError(f'File {isol_inp_file} not found')
307
    return isol_inp_file
308

    
309

    
310
def get_molec_file():
311
    molec_file = dos_inp.get('Isolated', 'molec_file')
312
    if not os.path.isfile(molec_file):
313
        logger.error(f'File {molec_file} not found')
314
        raise FileNotFoundError(f'File {molec_file} not found')
315
    return molec_file
316

    
317

    
318
def get_cluster_magns():
319
    clust_magns_vals = ['energy', 'moi']
320
    cluster_magns_str = dos_inp.get('Isolated', 'cluster_magns',
321
                                    fallback='energy')
322
    cluster_magns_str.replace(',', ' ').replace(';', ' ')
323
    cluster_magns = cluster_magns_str.split(' ')
324
    cluster_magns = [m.lower() for m in cluster_magns]
325
    for m in cluster_magns:
326
        check_expect_val(m, clust_magns_vals)
327
    return cluster_magns
328

    
329

    
330
def get_num_conformers():
331
    err_msg = num_error % ('num_conformers', 'positive integer')
332
    num_conformers = try_command(dos_inp.getint, [(ValueError, err_msg)],
333
                                 'Isolated', 'num_conformers', fallback=100)
334
    if num_conformers < 1:
335
        logger.error(err_msg)
336
        raise ValueError(err_msg)
337
    return num_conformers
338

    
339

    
340
def get_num_prom_cand():
341
    err_msg = num_error % ('num_prom_cand', 'positive integer')
342
    num_prom_cand = try_command(dos_inp.getint, [(ValueError, err_msg)],
343
                                'Isolated', 'num_prom_cand', fallback=3)
344
    if num_prom_cand < 1:
345
        logger.error(err_msg)
346
        raise ValueError(err_msg)
347
    return num_prom_cand
348

    
349

    
350
def get_iso_rmsd():
351
    err_msg = num_error % ('iso_rmsd', 'positive decimal number')
352
    iso_rmsd = try_command(dos_inp.getfloat, [(ValueError, err_msg)],
353
                           'Isolated', 'iso_rmsd', fallback=0.05)
354
    if iso_rmsd <= 0.0:
355
        logger.error(err_msg)
356
        raise ValueError(err_msg)
357
    return iso_rmsd
358

    
359

    
360
def get_min_confs():
361
    err_msg = "'min_confs' should be have a boolean value (True or False)"
362
    min_confs = try_command(dos_inp.getboolean,
363
                            [(ValueError, err_msg)],
364
                            'Isolated', 'min_confs', fallback=True)
365
    return min_confs
366

    
367

    
368
def get_screen_inp_file():
369
    screen_inp_file = dos_inp.get('Screening', 'screen_inp_file')
370
    if not os.path.isfile(screen_inp_file):
371
        logger.error(f'File {screen_inp_file} not found')
372
        raise FileNotFoundError(f'File {screen_inp_file} not found')
373
    return screen_inp_file
374

    
375

    
376
def get_sites():
377
    err_msg = 'The value of sites should be a list of atom numbers ' \
378
              '(ie. positive integers) or groups of atom numbers ' \
379
              'grouped by parentheses-like enclosers. \n' \
380
              'eg. 128,(135 138;141) 87 {45, 68}'
381
    # Convert the string into a list of lists
382
    sites = try_command(str2lst,
383
                        [(ValueError, err_msg), (AttributeError, err_msg)],
384
                        dos_inp.get('Screening', 'sites'))
385
    # Check all elements of the list (of lists) are positive integers
386
    for site in sites:
387
        if type(site) is list:
388
            for atom in site:
389
                if atom < 0:
390
                    logger.error(err_msg)
391
                    raise ValueError(err_msg)
392
        elif type(site) is int:
393
            if site < 0:
394
                logger.error(err_msg)
395
                raise ValueError(err_msg)
396
        else:
397
            logger.error(err_msg)
398
            raise ValueError(err_msg)
399

    
400
    return sites
401

    
402

    
403
def get_molec_ads_ctrs():
404
    err_msg = 'The value of molec_ads_ctrs should be a list of atom' \
405
              ' numbers (ie. positive integers) or groups of atom ' \
406
              'numbers enclosed by parentheses-like characters. \n' \
407
              'eg. 128,(135 138;141) 87 {45, 68}'
408
    # Convert the string into a list of lists
409
    molec_ads_ctrs = try_command(str2lst,
410
                                 [(ValueError, err_msg),
411
                                  (AttributeError, err_msg)],
412
                                 dos_inp.get('Screening', 'molec_ads_ctrs'))
413
    # Check all elements of the list (of lists) are positive integers
414
    for ctr in molec_ads_ctrs:
415
        if type(ctr) is list:
416
            for atom in ctr:
417
                if atom < 0:
418
                    logger.error(err_msg)
419
                    raise ValueError(err_msg)
420
        elif type(ctr) is int:
421
            if ctr < 0:
422
                logger.error(err_msg)
423
                raise ValueError(err_msg)
424
        else:
425
            logger.error(err_msg)
426
            raise ValueError(err_msg)
427

    
428
    return molec_ads_ctrs
429

    
430

    
431
def get_try_disso():
432
    err_msg = "try_disso should be have a boolean value (True or False)"
433
    try_disso = try_command(dos_inp.getboolean,
434
                            [(ValueError, err_msg)],
435
                            'Screening', 'try_disso', fallback=False)
436
    return try_disso
437

    
438

    
439
def get_pts_per_angle():
440
    err_msg = num_error % ('sample_points_per_angle',
441
                           'positive integer')
442
    pts_per_angle = try_command(dos_inp.getint,
443
                                [(ValueError, err_msg)],
444
                                'Screening', 'sample_points_per_angle',
445
                                fallback=3)
446

    
447
    return pts_per_angle
448

    
449

    
450
def get_coll_thrsld():
451
    err_msg = num_error % ('collision_threshold',
452
                           'positive decimal number')
453

    
454
    coll_thrsld = try_command(dos_inp.getfloat,
455
                              [(ValueError, err_msg)],
456
                              'Screening', 'collision_threshold', fallback=1.2)
457
    if coll_thrsld <= 0:
458
        logger.error(err_msg)
459
        raise ValueError(err_msg)
460

    
461
    return coll_thrsld
462

    
463

    
464
def get_screen_rmsd():
465
    err_msg = num_error % ('screen_rmsd', 'positive decimal number')
466
    screen_rmsd = try_command(dos_inp.getfloat,
467
                              [(ValueError, err_msg)],
468
                              'Screening', 'screen_rmsd', fallback=0.05)
469
    if screen_rmsd <= 0:
470
        logger.error(err_msg)
471
        raise ValueError(err_msg)
472

    
473
    return screen_rmsd
474

    
475

    
476
def get_coll_bottom_z():
477
    err_msg = num_error % ('collision_bottom_z', 'decimal number')
478
    coll_bottom_z = dos_inp.get('Screening', 'collision_bottom_z',
479
                                fallback="False")
480
    if coll_bottom_z.lower() in turn_false_answers:
481
        coll_bottom_z = False
482
    else:
483
        coll_bottom_z = try_command(float, [(ValueError, err_msg)],
484
                                    coll_bottom_z)
485

    
486
    return coll_bottom_z
487

    
488

    
489
def get_refine_inp_file():
490
    refine_inp_file = dos_inp.get('Refinement', 'refine_inp_file')
491
    if not os.path.isfile(refine_inp_file):
492
        logger.error(f'File {refine_inp_file} not found')
493
        raise FileNotFoundError(f'File {refine_inp_file} not found')
494

    
495
    return refine_inp_file
496

    
497

    
498
def get_energy_cutoff():
499
    err_msg = num_error % ('energy_cutoff', 'positive decimal number')
500
    energy_cutoff = try_command(dos_inp.getfloat,
501
                                [(ValueError, err_msg)],
502
                                'Refinement', 'energy_cutoff', fallback=0.5)
503
    if energy_cutoff < 0:
504
        logger.error(err_msg)
505
        raise ValueError(err_msg)
506
    return energy_cutoff
507

    
508

    
509
def read_input(in_file):
510
    err = False
511
    try:
512
        dos_inp.read(in_file)
513
    except MissingSectionHeaderError as e:
514
        logger.error('There are options in the input file without a Section '
515
                     'header')
516
        err = e
517
    except DuplicateOptionError as e:
518
        logger.error('There is an option in the input file that has been '
519
                     'specified more than once, possibly due to the lack of a '
520
                     'Section header')
521
        err = e
522
    except Exception as e:
523
        err = e
524
    else:
525
        err = False
526
    finally:
527
        if isinstance(err, BaseException):
528
            raise err
529

    
530
    return_vars = {}
531

    
532
    # Global
533
    if not dos_inp.has_section('Global'):
534
        logger.error(no_sect_err % 'Global')
535
        raise NoSectionError('Global')
536

    
537
    # Mandatory options
538
    # Checks whether the mandatory options 'run_type', 'code', etc. are present.
539
    glob_mand_opts = ['run_type', 'code', 'batch_q_sys', 'project_name']
540
    for opt in glob_mand_opts:
541
        if not dos_inp.has_option('Global', opt):
542
            logger.error(no_opt_err % (opt, 'Global'))
543
            raise NoOptionError(opt, 'Global')
544

    
545
    # Gets which sections are to be carried out
546
    isolated, screening, refinement = get_run_type()
547
    return_vars['isolated'] = isolated
548
    return_vars['screening'] = screening
549
    return_vars['refinement'] = refinement
550
    return_vars['code'] = get_code()
551
    return_vars['batch_q_sys'] = get_batch_q_sys()
552

    
553
    # Dependent options:
554
    return_vars['subm_script'] = get_subm_script()
555
    if return_vars['batch_q_sys'] != 'local' and not return_vars['subm_script']:
556
        sub_err = "'subm_script' must be provided if 'batch_q_sys' is not local"
557
        logger.error(sub_err)
558
        raise NoOptionError(opt, 'Global')
559

    
560
    # Facultative options (Default/Fallback value present)
561
    return_vars['project_name'] = get_project_name()
562
    return_vars['relaunch_err'] = get_relaunch_err()
563
    return_vars['max_qw'] = get_max_qw()
564
    return_vars['special_atoms'] = get_special_atoms()
565

    
566
    # Isolated
567
    if isolated:
568
        if not dos_inp.has_section('Isolated'):
569
            logger.error(no_sect_err % 'Isolated')
570
            raise NoSectionError('Isolated')
571
        # Mandatory options
572
        # Checks whether the mandatory options are present.
573
        iso_mand_opts = ['isol_inp_file', 'molec_file']
574
        for opt in iso_mand_opts:
575
            if not dos_inp.has_option('Isolated', opt):
576
                logger.error(no_opt_err % (opt, 'Isolated'))
577
                raise NoOptionError(opt, 'Isolated')
578
        return_vars['isol_inp_file'] = get_isol_inp_file()
579
        return_vars['molec_file'] = get_molec_file()
580

    
581
        # Facultative options (Default/Fallback value present)
582
        return_vars['cluster_magns'] = get_cluster_magns()
583
        return_vars['num_conformers'] = get_num_conformers()
584
        # return_vars['num_prom_cand'] = get_num_prom_cand()
585
        # return_vars['iso_rmsd'] = get_iso_rmsd()
586
        return_vars['min_confs'] = get_min_confs()
587

    
588
    # Screening
589
    if screening:
590
        if not dos_inp.has_section('Screening'):
591
            logger.error(no_sect_err % 'Screening')
592
            raise NoSectionError('Screening')
593
        # Mandatory options:
594
        # Checks whether the mandatory options are present.
595
        screen_mand_opts = ['sites', 'molec_ads_ctrs', 'screen_inp_file']
596
        for opt in screen_mand_opts:
597
            if not dos_inp.has_option('Screening', opt):
598
                logger.error(no_opt_err % (opt, 'Screening'))
599
                raise NoOptionError(opt, 'Screening')
600
        return_vars['screen_inp_file'] = get_screen_inp_file()
601
        return_vars['sites'] = get_sites()
602
        return_vars['molec_ads_ctrs'] = get_molec_ads_ctrs()
603

    
604
        # Facultative options (Default value present)
605
        return_vars['try_disso'] = get_try_disso()
606
        return_vars['sample_points_per_angle'] = get_pts_per_angle()
607
        return_vars['collision_threshold'] = get_coll_thrsld()
608
        # return_vars['screen_rmsd'] = get_screen_rmsd()
609
        return_vars['collision_bottom_z'] = get_coll_bottom_z()
610

    
611
    # Refinement
612
    if refinement:
613
        if not dos_inp.has_section('Refinement'):
614
            logger.error(no_sect_err % 'Refinement')
615
            raise NoSectionError('Refinement')
616
        # Mandatory options
617
        # Checks whether the mandatory options are present.
618
        ref_mand_opts = ['refine_inp_file']
619
        for opt in ref_mand_opts:
620
            if not dos_inp.has_option('Refinement', opt):
621
                logger.error(no_opt_err % (opt, 'Refinement'))
622
                raise NoOptionError(opt, 'Refinement')
623
        return_vars['refine_inp_file'] = get_refine_inp_file()
624

    
625
        # Facultative options (Default value present)
626
        return_vars['energy_cutoff'] = get_energy_cutoff()
627
        # end energy_cutoff
628

    
629
    return_vars_str = "\n\t".join([str(key) + ": " + str(val)
630
                                   for key, val in return_vars.items()])
631
    logger.info(
632
        f'Correctly read {in_file} parameters: \n\n\t{return_vars_str}\n')
633

    
634
    return return_vars
635

    
636

    
637
if __name__ == "__main__":
638
    import sys
639

    
640
    print(read_input(sys.argv[1]))