Coverage for /builds/kinetik161/ase/ase/cli/find.py: 20.55%
73 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-12-10 11:04 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-12-10 11:04 +0000
1# Note:
2# Try to avoid module level import statements here to reduce
3# import time during CLI execution
4import sys
7class CLICommand:
8 """Find files with atoms in them.
10 Search through files known to ASE applying a query to filter the results.
12 See https://wiki.fysik.dtu.dk/ase/ase/db/db.html#querying for more
13 informations on how to construct the query string.
14 """
16 @staticmethod
17 def add_arguments(parser):
18 parser.add_argument('folder', help='Folder to look in.')
19 parser.add_argument(
20 'query', nargs='?',
21 help='Examples: More than 2 hydrogens and no silver: "H>2,Ag=0". '
22 'More than 1000 atoms: "natoms>1000". '
23 'Slab geometry containing Cu and Ni: "pbc=TTF,Cu,Ni".')
24 parser.add_argument('-v', '--verbose', action='store_true',
25 help='More output.')
26 parser.add_argument('-l', '--long', action='store_true',
27 help='Show also periodic boundary conditions, '
28 'chemical formula and filetype.')
29 parser.add_argument('-i', '--include', help='Include only filenames '
30 'ending with given strings. Example: '
31 '"-i .xyz,.traj".')
32 parser.add_argument('-x', '--exclude', help='Exclude filenames '
33 'ending with given strings. Example: '
34 '"-x .cif".')
36 @staticmethod
37 def run(args):
38 main(args)
41def main(args):
42 from ase.db.core import parse_selection
44 query = parse_selection(args.query)
45 include = args.include.split(',') if args.include else []
46 exclude = args.exclude.split(',') if args.exclude else []
48 if args.long:
49 print('pbc {:10} {:15} path'.format('formula', 'filetype'))
51 for path in allpaths(args.folder, include, exclude):
52 format, row = check(path, query, args.verbose)
53 if format:
54 if args.long:
55 print('{} {:10} {:15} {}'
56 .format(''.join(str(p) for p in row.pbc.astype(int)),
57 row.formula,
58 format,
59 path))
60 else:
61 print(path)
64def allpaths(folder, include, exclude):
65 """Generate paths."""
66 import os
67 import os.path as op
69 exclude += ['.py', '.pyc']
70 for dirpath, dirnames, filenames in os.walk(folder):
71 for name in filenames:
72 if any(name.endswith(ext) for ext in exclude):
73 continue
74 if include:
75 for ext in include:
76 if name.endswith(ext):
77 break
78 else:
79 continue
80 path = op.join(dirpath, name)
81 yield path
83 # Skip .git, __pycache__ and friends:
84 dirnames[:] = (name for name in dirnames if name[0] not in '._')
87def check(path, query, verbose):
88 """Check a path.
90 Returns a (filetype, AtomsRow object) tuple.
91 """
92 from ase.db import connect
93 from ase.db.jsondb import JSONDatabase
94 from ase.db.row import atoms2dict
95 from ase.io import read
96 from ase.io.formats import UnknownFileTypeError, filetype
98 class FakeDB(JSONDatabase):
99 def __init__(self, atoms):
100 self.bigdct = {1: atoms2dict(atoms)}
102 def _read_json(self):
103 return self.bigdct, [1], 2
105 try:
106 format = filetype(path, guess=False)
107 except (OSError, UnknownFileTypeError):
108 return '', None
110 if format in ['db', 'json']:
111 db = connect(path)
112 else:
113 try:
114 atoms = read(path, format=format)
115 except Exception as x:
116 if verbose:
117 print(path + ':', x, file=sys.stderr)
118 return '', None
119 db = FakeDB(atoms)
121 try:
122 for row in db._select(*query):
123 return format, row
124 except Exception as x:
125 if verbose:
126 print(path + ':', x, file=sys.stderr)
128 return '', None