Passed
Push — master ( eb28f3...7c7660 )
by Daniel
04:02
created

amd.cli   A

Complexity

Total Complexity 7

Size/Duplication

Total Lines 114
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 7
eloc 75
dl 0
loc 114
rs 10
c 0
b 0
f 0

1 Function

Rating   Name   Duplication   Size   Complexity  
C main() 0 104 7
1
"""Command line interface for :func:`amd.compare() <.compare.compare>`.
2
"""
3
4
import argparse
5
import sys
6
7
from .compare import compare
8
9
10
def main():
11
    """Entry point for command line interface for
12
    :func:`amd.compare() <.compare.compare>.
13
    """
14
15
    desc = "Compare crystals by PDD or AMD from the command line. Given one " \
16
           "or two paths to cifs/folders, lists of CSD refcodes or periodic " \
17
           "sets, compare them and return a DataFrame of the distance " \
18
           "matrix. Default is to comapre by AMD with k = 100. Accepts most " \
19
           "keyword arguments accepted by amd's CIF/CSD readers and " \
20
           "comparison functions."
21
22
    parser = argparse.ArgumentParser(description=desc)
23
24
    parser.add_argument('paths_or_refcodes', type=str, nargs='+',
25
        help='(str) One or two paths to files or folders, or a collection ' \
26
             'of CSD refcodes if csd-python-api is installed.')
27
    parser.add_argument('--outpath', '-o', type=str,
28
        help='(str) Path of the output file.')
29
    parser.add_argument('--format', '-f', type=str, default='csv', 
30
        help='(str) Format of the output file, default csv.')
31
32
    # amd.compare args 
33
    parser.add_argument(
34
        '--by', '-b', type=str, default='AMD', choices=['AMD', 'PDD'],
35
        help='(str) Use AMD or PDD to compare crystals.')
36
    parser.add_argument('--k', '-k', type=int, default=100,
37
        help='(int) Number of neighbour atoms to use for AMD/PDD.')
38
    parser.add_argument('--nearest', '-n', type=int, default=None,
39
        help='(int) Find n nearest neighbours instead of a full distance ' \
40
             'matrix between crystals.')
41
42
    # Reading args
43
    parser.add_argument(
44
        '--supress_warnings', default=False, action='store_true',
45
        help='(flag) Do not show warnings encountered during reading.')
46
    parser.add_argument('--reader', '-r', type=str, default='ase',
47
        choices=['ase', 'pycodcif', 'ccdc', 'pymatgen', 'gemmi'],
48
        help='(str) Backend package used to parse files, default ase.')
49
    parser.add_argument('--remove_hydrogens', default=False,
50
        action='store_true', help='(flag) Remove Hydrogen atoms.')
51
    parser.add_argument('--disorder', type=str, default='skip',
52
        choices=['skip', 'ordered_sites', 'all_sites'],
53
        help='(str) Control how disordered structures are handled.')
54
    parser.add_argument(
55
        '--heaviest_component', default=False, action='store_true',
56
        help='(flag) (csd-python-api only) Keep only the heaviest part of ' \
57
             'the asymmetric unit, intended for removing solvents.')
58
    parser.add_argument(
59
        '--molecular_centres', default=False, action='store_true',
60
        help='(flag) (csd-python-api only) Uses the centres of molecules ' \
61
             'for comparisons instead of atoms.')
62
    parser.add_argument('--families', default=False, action='store_true',
63
        help='(flag) (csd-python-api only) Interpret path_or_refcodes as ' \
64
             'refcode families.')
65
66
    # PDD args
67
    parser.add_argument('--collapse_tol', type=float, default=1e-4,
68
        help='(float) Tolerance for collapsing rows of PDDs.')
69
70
    # compare args
71
    parser.add_argument('--metric', type=str, default='chebyshev',
72
        help='(str) Metric used to compare AMDs/rows of PDDs, default chebyshev.')
73
    parser.add_argument('--n_jobs', type=int, default=1,
74
        help='(int) Number of cores to use for multiprocessing when comparing PDDs.')
75
    parser.add_argument('--verbose', type=int, default=1,
76
        help='(int) Print an ETA to the terminal when comparing PDDs. Passed to joblib.Parallel if using multiprocessing.')
77
    parser.add_argument('--low_memory', default=False, action='store_true',
78
        help='(flag) Use an more memory efficient (but slower) method for AMD comparisons.')
79
80
    # Remove some arguments before passing others to amd.compare
81
    kwargs = vars(parser.parse_args())
82
    path_or_refcodes = kwargs.pop('path_or_refcodes')
83
    outpath = kwargs.pop('outpath', None)
84
    if outpath is None:
85
        outpath = f"{kwargs['by']}_k={kwargs['k']}_dist_matrix"
86
    ext = kwargs.pop('format', 'csv')
87
88
    # Parameter is show_warnings, here it's a flag supress_warnings
89
    kwargs['show_warnings'] = not kwargs['supress_warnings']
90
    kwargs.pop('supress_warnings', None)
91
92
    crystals = path_or_refcodes[0]
93
    crystals_ = None
94
    if len(path_or_refcodes) == 2:
95
        crystals_ = path_or_refcodes[1]
96
    elif len(path_or_refcodes) > 2:
97
        msg = 'amd.compare accepts one or two collections of crystals for comparison.'
98
        raise ValueError(msg)
99
100
    df = compare(crystals, crystals_, **kwargs)
101
102
    if kwargs['verbose']:
103
        sys.stdout.write(df)
104
105
    if not outpath.endswith('.' + ext):
106
        outpath += '.' + ext
107
108
    try:
109
        output_func = getattr(df, 'to_' + ext)
110
        output_func(outpath)
111
    except AttributeError:
112
        sys.stdout.write(f'Unknown format {ext}, using csv.')
113
        df.to_csv(outpath + '.csv')
114