mlatom 2.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. MLatom/ML_NEA.py +2697 -0
  2. MLatom/MLatom.py +151 -0
  3. MLatom/MLatomF +0 -0
  4. MLatom/MLtasks.py +767 -0
  5. MLatom/__init__.py +0 -0
  6. MLatom/args_class.py +396 -0
  7. MLatom/cs.so +0 -0
  8. MLatom/doc.py +620 -0
  9. MLatom/header.py +64 -0
  10. MLatom/interface_MLatomF.py +87 -0
  11. MLatom/interfaces/DeePMDkit/DP_inference.py +20 -0
  12. MLatom/interfaces/DeePMDkit/__init__.py +0 -0
  13. MLatom/interfaces/DeePMDkit/interface_DeePMDkit.py +327 -0
  14. MLatom/interfaces/DeePMDkit/template.json +70 -0
  15. MLatom/interfaces/GAP/__init__.py +0 -0
  16. MLatom/interfaces/GAP/interface_GAP.py +415 -0
  17. MLatom/interfaces/PhysNet/PhysNet_predict.py +180 -0
  18. MLatom/interfaces/PhysNet/PhysNet_train.py +425 -0
  19. MLatom/interfaces/PhysNet/__init__.py +0 -0
  20. MLatom/interfaces/PhysNet/interface_PhysNet.py +270 -0
  21. MLatom/interfaces/TorchANI/TorchANI_predict.py +82 -0
  22. MLatom/interfaces/TorchANI/TorchANI_train.py +217 -0
  23. MLatom/interfaces/TorchANI/__init__.py +0 -0
  24. MLatom/interfaces/TorchANI/interface_TorchANI.py +323 -0
  25. MLatom/interfaces/__init__.py +0 -0
  26. MLatom/interfaces/sGDML/__init__.py +0 -0
  27. MLatom/interfaces/sGDML/interface_sGDML.py +276 -0
  28. MLatom/interfaces/sGDML/sgdml_dataset_from_extxyz.py +199 -0
  29. MLatom/ref.json +23 -0
  30. MLatom/sliceData.py +334 -0
  31. MLatom/stopper.py +17 -0
  32. MLatom-2.0.0.data/scripts/MLatomF +12 -0
  33. MLatom-2.0.0.data/scripts/mlatom +12 -0
  34. MLatom-2.0.0.dist-info/LICENSE.txt +251 -0
  35. MLatom-2.0.0.dist-info/METADATA +149 -0
  36. MLatom-2.0.0.dist-info/RECORD +38 -0
  37. MLatom-2.0.0.dist-info/WHEEL +5 -0
  38. MLatom-2.0.0.dist-info/top_level.txt +1 -0
MLatom/__init__.py ADDED
File without changes
MLatom/args_class.py ADDED
@@ -0,0 +1,396 @@
1
+ #!/usr/bin/env python3
2
+ '''
3
+ !---------------------------------------------------------------------------!
4
+ ! args_class: handling input of MLatom !
5
+ ! Implementations by: Bao-Xin Xue !
6
+ !---------------------------------------------------------------------------!
7
+ '''
8
+
9
+ from collections import defaultdict, UserDict
10
+ from os import replace
11
+ from typing import Callable, DefaultDict, Sequence, Tuple, Union
12
+ from typing import List, Tuple, Dict, Set, Any
13
+ from copy import copy
14
+ import re
15
+ import stopper
16
+
17
+ try:
18
+ from doc import Doc
19
+ except:
20
+ Doc = None
21
+
22
+
23
+ class KeyNotFoundException(Exception):
24
+ pass
25
+
26
+
27
+ class DuplicatedKeyException(Exception):
28
+ pass
29
+
30
+
31
+ class AttributeDict(UserDict):
32
+ data: Dict[Any, Any]
33
+ lower_key_set: Set[Any]
34
+ lower_key_to_key: Dict[str, str]
35
+ attribute_dict_variable = ['data', 'lower_key_set', 'lower_key_to_key', 'attribute_dict_variable']
36
+
37
+ def __init__(self) -> None:
38
+ self.__dict__['data'] = {}
39
+ self.__dict__['lower_key_set'] = set()
40
+ self.__dict__['lower_key_to_key'] = {}
41
+ self.__dict__['writable_flag'] = False
42
+
43
+ @classmethod
44
+ def merge_dict(cls, my_dict: 'AttributeDict', other: Dict[str, Any]) -> None:
45
+ for other_key in other.keys():
46
+ other_key_strip = other_key.strip() # for the usage of my_dict
47
+ other_key_lower = other_key_strip.lower() # for the usage of my_dict.lower_key_set
48
+ if other_key_lower in my_dict.lower_key_set:
49
+ if type(other[other_key]) in [dict, cls]:
50
+ if type(my_dict[other_key_strip]) is not cls:
51
+ my_dict[other_key_strip] = AttributeDict()
52
+ cls.merge_dict(my_dict[other_key_strip], other[other_key])
53
+ else:
54
+ my_dict[other_key_strip] = other[other_key]
55
+ else:
56
+ my_dict.lower_key_set.add(other_key_lower)
57
+ my_dict.lower_key_to_key[other_key_lower] = other_key_strip
58
+ my_dict[other_key_strip] = other[other_key]
59
+
60
+ def key_in_dict(self, name: str) -> bool:
61
+ lower_key = name.lower().strip()
62
+ return lower_key in self.lower_key_set
63
+
64
+ @classmethod
65
+ def dict_to_attributedict(cls, d: Dict[str, Any]) -> 'AttributeDict':
66
+ new_dict = cls()
67
+ for key, value in d.items():
68
+ if type(value) is dict:
69
+ new_value = cls.dict_to_attributedict(value)
70
+ new_dict[key] = new_value
71
+ else:
72
+ new_dict[key] = value
73
+ return new_dict
74
+
75
+ @classmethod
76
+ def normal_dict(cls, d: 'AttributeDict') -> Dict[str, Any]:
77
+ new_dict = {}
78
+ for key, value in d.items():
79
+ if type(value) in [cls, dict]:
80
+ new_dict[key] = cls.normal_dict(value)
81
+ else:
82
+ new_dict[key] = value
83
+ return new_dict
84
+
85
+ def _raise_internal_key_error(self, name: str) -> None:
86
+ if name.lower() in self.attribute_dict_variable:
87
+ raise KeyError(name)
88
+
89
+ def __setattr__(self, name: str, value: Any) -> None:
90
+ if name.startswith('__') or (name in self.__dict__):
91
+ super(AttributeDict, self).__setattr__(name, value)
92
+ else:
93
+ self.__setitem__(name, value)
94
+
95
+ # def __getattribute__(self, name: str) -> Any:
96
+ # if name in super(AttributeDict, self).__getattribute__('attribute_dict_variable'):
97
+ # raise KeyError(f'{name} can not appears on the args_class.{self.__class__}')
98
+ # return super(AttributeDict, self).__getattribute__(name)
99
+
100
+ def __getattr__(self, name: str) -> Any:
101
+ if not self.key_in_dict(name):
102
+ self[name] = self.__class__()
103
+ return self.__getitem__(name)
104
+
105
+ def __setitem__(self, name: str, value: Any) -> Any:
106
+ self._raise_internal_key_error(name)
107
+ key_strip = name.strip()
108
+ key_lower = key_strip.lower()
109
+ if type(value) is dict:
110
+ new_value = self.dict_to_attributedict(value)
111
+ else:
112
+ new_value = copy(value)
113
+ if key_lower in self.lower_key_set:
114
+ true_key = self.lower_key_to_key[key_lower]
115
+ self.data[true_key] = new_value
116
+ else:
117
+ self.lower_key_set.add(key_lower)
118
+ self.lower_key_to_key[key_lower] = key_strip
119
+ self.data[key_strip] = new_value
120
+
121
+ def __getitem__(self, name: str) -> Any:
122
+ self._raise_internal_key_error(name)
123
+ if name.startswith('__') or (name in self.__dict__):
124
+ return self.__dict__[name]
125
+ lower_key = name.lower().strip()
126
+ if lower_key in self.lower_key_set:
127
+ return self.data[self.lower_key_to_key[lower_key]]
128
+ raise KeyError(name)
129
+
130
+
131
+ class ArgsBase():
132
+ """As a argument parsing base class to be extended.
133
+
134
+ basic usage:
135
+ 1. extend this class in your class argument class
136
+ 2. use add_default_dict_args or add_dict_args or add_keyword_value_args to add default key-value pair
137
+ 3. use parse_input_file or parse_input_content to parse argument content
138
+ 4. use self.args_dict to get a argument dict OR self.args_string_list(excluse) to get a list of argument string
139
+
140
+ Other feature:
141
+ 1. set_ignore_keyword_list: to exclusive some keyword
142
+ 2. exists_key: to judge whether key exists (for safely check) (now only support first layer check)
143
+ 3. set_keyword_alias(standard_key, [alias_key1, alias_key2, ...])
144
+ 4. can use add_dict_args to add a dict to the ArgsBase
145
+
146
+ Attention:
147
+ 1. only when set dict_args and read file content can set new argument
148
+ 2. user can use args.xxx = yyy refresh the value, but only when the key exists, the dict will refresh,
149
+ OR it will only add a new member var on args, so please combine it with `exists_key` to check it.
150
+ """
151
+ ignore_list: List[str] = []
152
+ keyword_alias_dict: Dict[str, List[str]] = {}
153
+ writable: bool = True
154
+ data: AttributeDict
155
+ def __init__(self) -> None:
156
+ self.__dict__['data'] = AttributeDict()
157
+ self.__dict__['writable'] = False
158
+
159
+ def add_default_dict_args(self, keyword_list: List[str], type_or_Callable_or_value: Union[type, Callable[..., Any], Any]):
160
+ self.writable = True
161
+ if type(type_or_Callable_or_value) in [type, Callable]:
162
+ dd: DefaultDict[str, Any] = defaultdict(type_or_Callable_or_value)
163
+ for key in keyword_list:
164
+ self.data[key] = dd[key]
165
+ else:
166
+ for key in keyword_list:
167
+ self.data[key] = copy(type_or_Callable_or_value)
168
+ self.writable = False
169
+
170
+ # @singledispatch
171
+ def add_dict_args(self, dict: Dict[str, Any]):
172
+ AttributeDict.merge_dict(self.data, dict)
173
+
174
+ def add_keyword_value_args(self, keyword_list: List[str], value_list: List[Any]):
175
+ if len(keyword_list) != len(value_list):
176
+ self._raise_error(f'Internal Error: ArgsBase.add_keyword_value_args: the length is not equal in keyword_list and value_list')
177
+ d = { k: v for k, v in zip(keyword_list, value_list)}
178
+ self.add_dict_args(d)
179
+
180
+ @staticmethod
181
+ def _args_extractor(string: str) -> List[str]:
182
+ pair_dict = {'(': ')', '[': ']', '{': '}', '<': '>', "'": "'", '"': '"'}
183
+ pair_level = 0
184
+ pair_right: List[str] = []
185
+ tmp = ''
186
+ prev = ''
187
+ out_string_list: List[str] = []
188
+ for chr in string:
189
+ pair_right_last = pair_right[-1] if pair_right else ''
190
+ if chr in pair_dict.keys() and chr != pair_right_last:
191
+ pair_level += 1
192
+ pair_right.append(pair_dict[chr])
193
+ elif chr == pair_right_last:
194
+ pair_level -= 1
195
+ pair_right.pop()
196
+ elif chr == ' ' and pair_level == 0 and prev.strip(): # end
197
+ out_string_list.append(tmp)
198
+ tmp = ''
199
+ prev = chr
200
+ continue
201
+ if '"' in pair_right or "'" in pair_right:
202
+ tmp += chr
203
+ else:
204
+ tmp += chr.strip()
205
+ prev = chr
206
+ if pair_level:
207
+ stopper.stopMLatom(f'pair character unmatched args: "{tmp}"')
208
+ else:
209
+ if tmp: out_string_list.append(tmp)
210
+ return out_string_list
211
+
212
+ def parse_input_file(self, file: str):
213
+ try:
214
+ with open(file) as f:
215
+ content = f.read().splitlines()
216
+ except:
217
+ self._raise_error(f'can not open file {file}! exit!'); exit()
218
+ self.parse_input_content(content)
219
+
220
+ def parse_input_content(self, content: Union[List[str], str]):
221
+ help = False
222
+ if type(content) is str:
223
+ content = content.splitlines()
224
+ for c in self._clean_input_content(content):
225
+ splitted = c.split('=')
226
+ if len(splitted) == 1:
227
+ key = splitted[0]
228
+ if key.lower() in ['help', '-help', '-h', '--help']:
229
+ help = True
230
+ elif key.lower() in self.ignore_list:
231
+ pass
232
+ else:
233
+ restored_key = self._restore_alias_key(key)
234
+ self.data[restored_key] = True
235
+ elif len(splitted) == 2:
236
+ key, value = tuple(map(lambda x: x.strip(), splitted))
237
+ key, value = self._multi_level_dict(key, value) # has changed the type of value
238
+ key = self._restore_alias_key(key)
239
+ if type(value) in [dict, AttributeDict]:
240
+ AttributeDict.merge_dict(self.data, {key: value})
241
+ continue
242
+ else:
243
+ self.data[key] = value
244
+ else:
245
+ self._raise_error(f'error happends at your input file, error content:\n {c}')
246
+ if help:
247
+ self._print_doc()
248
+
249
+ @classmethod
250
+ def _multi_level_dict(cls, key: str, value: Any) -> Tuple[str, Union[AttributeDict, Dict[str, Union[str, Dict[str, Any]]]]]:
251
+ split_key = key.split('.')
252
+ real_key = split_key[0]
253
+ inner_value = cls._convert_to_value_with_type(copy(value))
254
+ for sub_key in split_key[1:][::-1]:
255
+ outter_dict = AttributeDict()
256
+ outter_dict[sub_key] = inner_value
257
+ inner_value = outter_dict
258
+ return real_key, inner_value
259
+
260
+ def _print_doc(self):
261
+ try: Doc.printDoc(self.args_dict)
262
+ except: self._warning_print('Doc not imported')
263
+ stopper.stopMLatom('')
264
+
265
+ @classmethod
266
+ def _clean_input_content(cls, content: List[str]) -> List[str]:
267
+ to_return: List[str] = []
268
+ for c in content:
269
+ usable = c.split('#')[0].strip()
270
+ while usable.find(' =') != -1:
271
+ usable = usable.replace(' =', '=')
272
+ while usable.find('= ') != -1:
273
+ usable = usable.replace('= ', '=')
274
+ to_return.extend(cls._args_extractor(usable))
275
+ return to_return
276
+
277
+ @property
278
+ def args_dict(self) -> Dict[str, Any]:
279
+ return AttributeDict.normal_dict(self.data)
280
+
281
+ def args_string_list(self, exclusive: List[Any]=[]) -> List[str]:
282
+ l = []
283
+ for key, value in self.args_dict.items():
284
+ if exclusive:
285
+ if value in exclusive:
286
+ continue
287
+ if value is True:
288
+ l.append(key)
289
+ elif value is False:
290
+ continue
291
+ else:
292
+ if type(value) is dict:
293
+ l.extend(self._dict_dot_expression(value, key))
294
+ else:
295
+ l.append(f'{key}={value}')
296
+ # l.append(f'{key}={value}')
297
+ return l
298
+
299
+ def _dict_dot_expression(self, d: Dict[str, Union[Dict[str, Any], Any]], key_pre_str: str='') -> List[str]:
300
+ str_list = []
301
+ for key, value in d.items():
302
+ if type(value) is dict:
303
+ str_list.extend(self._dict_dot_expression(value, f'{key_pre_str}.{key}'))
304
+ else:
305
+ str_list.append(f'{key_pre_str}.{key}={value}')
306
+ return str_list
307
+
308
+
309
+ def exists_key(self, name: str) -> bool:
310
+ return self.exists_key(name)
311
+
312
+ def set_ignore_keyword_list(self, kw_or_list: Union[str, List[str]]):
313
+ if type(kw_or_list) in [list, tuple]:
314
+ self.ignore_list.extend(kw_or_list)
315
+ elif type(kw_or_list) is str:
316
+ self.ignore_list.append(kw_or_list)
317
+ else:
318
+ self._raise_error(f'Internal error: "set_ignore_keyword_list" can not be {kw_or_list}')
319
+
320
+ def __getattr__(self, name: str) -> Any:
321
+ restored_name = self._restore_alias_key(name)
322
+ return self.data[restored_name]
323
+
324
+ def __setattr__(self, name: str, value: Any) -> None:
325
+ self.__setitem__(name, value)
326
+ # restored_name = self._restore_alias_key(name)
327
+ # if self.data.key_in_dict(restored_name):
328
+ # self.data[restored_name] = value
329
+ # else:
330
+ # self.__dict__[name] = value
331
+
332
+ def set_keyword_alias(self, standard: str, alias: Union[str, Sequence[str]]) -> None:
333
+ if type(alias) is str:
334
+ self.keyword_alias_dict[standard] = [alias.lower()]
335
+ else:
336
+ self.keyword_alias_dict[standard] = list(map(lambda x: x.lower(), alias))
337
+
338
+ def _restore_alias_key(self, key: str) -> str:
339
+ for std_key, alias_list in self.keyword_alias_dict.items():
340
+ if key.lower().strip() in alias_list:
341
+ return std_key
342
+ return key
343
+
344
+ def __getitem__(self, name: str) -> Any:
345
+ restored_name = self._restore_alias_key(name)
346
+ return self.data[restored_name]
347
+
348
+ def __setitem__(self, name: str, value: Any) -> None:
349
+ restored_name = self._restore_alias_key(name)
350
+ if self.data.key_in_dict(restored_name):
351
+ self.data[restored_name] = value
352
+ else:
353
+ self.__dict__[name] = value
354
+
355
+ @staticmethod
356
+ def _raise_error(content: str) -> None:
357
+ print('WARNING ' * 10)
358
+ print(' <!> %s <!>' % content)
359
+ print('WARNING ' * 10)
360
+ exit()
361
+
362
+ @staticmethod
363
+ def _warning_print(warning: str) -> None:
364
+ print('-' * 80)
365
+ print(' warning: %s :warning' % warning)
366
+ print('-' * 80)
367
+
368
+ @staticmethod
369
+ def _convert_to_value_with_type(value: Any) -> Any:
370
+ if type(value) in [dict, AttributeDict]:
371
+ return value
372
+ if value.strip().lower() == 'true':
373
+ return True
374
+ elif value.strip().lower() == 'false':
375
+ return False
376
+ else:
377
+ try:
378
+ tmp = int(value)
379
+ except:
380
+ try:
381
+ tmp = float(value)
382
+ except:
383
+ return value
384
+ else:
385
+ return tmp
386
+ else:
387
+ return tmp
388
+
389
+
390
+ if __name__ == '__main__':
391
+ try:
392
+ args = ArgsBase()
393
+ args.parse_input_file('inp')
394
+ except: pass
395
+ print( 'warning: you are directly running the module: args_class, '\
396
+ 'which should be extended by a class, not run it.')
MLatom/cs.so ADDED
Binary file