Skip to content

Commit 4d9359a

Browse files
docs: add docs for Format (#451)
Signed-off-by: Jinzhe Zeng <jinzhe.zeng@rutgers.edu> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 6232559 commit 4d9359a

1 file changed

Lines changed: 211 additions & 15 deletions

File tree

dpdata/format.py

Lines changed: 211 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,36 +6,158 @@
66

77

88
class Format(ABC):
9+
"""The abstract base class for all formats.
10+
11+
To add a new format, one should create a new class inherited from this class, and then
12+
13+
- implement several methods, such as :meth:`from_system`;
14+
- register the format with a key;
15+
- add documentation in the class docstring;
16+
17+
The new format can be either insider or outside the package.
18+
"""
19+
920
__FormatPlugin = Plugin()
1021
__FromPlugin = Plugin()
1122
__ToPlugin = Plugin()
1223

1324
@staticmethod
1425
def register(key):
26+
"""Register a format plugin.
27+
28+
By default, after a format plugin is registered, the following methods
29+
will be registered as well for :meth:`System`, :meth:`LabeledSystem`, :meth:`MultiSystems`, and
30+
:meth:`BondOrderSystem`:
31+
32+
- from_{key.replace('/', '_')}
33+
- to_{key.replace('/', '_')}
34+
- from({key}, ...)
35+
- to({key}, ...)
36+
37+
The decorator should be explicitly executed before :mod:`dpdata.system`
38+
is imported. A module will be imported automatically if it
39+
40+
- is a submodule of :mod:`dpdata.plugins`;
41+
- is registered at the `dpdata.plugins` entry point
42+
43+
Parameters
44+
----------
45+
key : str
46+
The key to register the plugin.
47+
48+
Returns
49+
-------
50+
function
51+
The decorator function.
52+
53+
Examples
54+
--------
55+
Register a format plugin:
56+
57+
>>> @Format.register('test')
58+
... @Format.register('test2')
59+
... class TestFormat(Format):
60+
... pass
61+
"""
1562
return Format.__FormatPlugin.register(key)
1663

1764
@staticmethod
1865
def register_from(key):
66+
"""Register a from method if the target method name is not default.
67+
68+
Parameters
69+
----------
70+
key : str
71+
The key to register the plugin.
72+
73+
Returns
74+
-------
75+
function
76+
The decorator function.
77+
78+
Examples
79+
--------
80+
Register a from method:
81+
82+
>>> @Format.register_from('from_test_haha')
83+
... @Format.register('test)
84+
... class TestFormat(Format):
85+
... pass
86+
87+
This will register a from method named from_test_haha, although the
88+
format name is test.
89+
"""
1990
return Format.__FromPlugin.register(key)
2091

2192
@staticmethod
2293
def register_to(key):
94+
"""Register a to method if the target method name is not default.
95+
96+
Parameters
97+
----------
98+
key : str
99+
The key to register the plugin.
100+
101+
Returns
102+
-------
103+
function
104+
The decorator function.
105+
106+
Examples
107+
--------
108+
Register a to method:
109+
110+
>>> @Format.register_to('to_test_haha')
111+
... @Format.register('test')
112+
... class TestFormat(Format):
113+
... pass
114+
115+
This will register a to method named to_test_haha, although the
116+
format name is test.
117+
"""
23118
return Format.__ToPlugin.register(key)
24119

25120
@staticmethod
26121
def get_formats():
122+
"""Get all registered formats."""
27123
return Format.__FormatPlugin.plugins
28124

29125
@staticmethod
30126
def get_from_methods():
127+
"""Get all registered from methods."""
31128
return Format.__FromPlugin.plugins
32129

33130
@staticmethod
34131
def get_to_methods():
132+
"""Get all registered to methods."""
35133
return Format.__ToPlugin.plugins
36134

37135
@staticmethod
38136
def post(func_name):
137+
"""Register a post function for from method.
138+
139+
Such function will be called after the "from" method is called.
140+
141+
Parameters
142+
----------
143+
func_name : str or list of str
144+
The name of the post function.
145+
146+
Returns
147+
-------
148+
function
149+
The decorator function.
150+
151+
Examples
152+
--------
153+
Register a post function:
154+
155+
>>> @Format.post('remove_pbc')
156+
... @Format.register('test')
157+
... class TestFormat(Format):
158+
... pass
159+
"""
160+
39161
def decorator(object):
40162
if not isinstance(func_name, (list, tuple, set)):
41163
object.post_func = (func_name,)
@@ -46,60 +168,119 @@ def decorator(object):
46168
return decorator
47169

48170
def from_system(self, file_name, **kwargs):
49-
"""System.from.
171+
"""Implement System.from that converts from this format to System.
50172
51173
Parameters
52174
----------
53175
file_name : str
54-
file name
176+
file name, i.e. the first argument
55177
**kwargs : dict
56-
other parameters
178+
keyword arguments that will be passed from the method
57179
58180
Returns
59181
-------
60-
data: dict
61-
system data
182+
data : dict
183+
system data, whose keys are defined in System.DTYPES
62184
"""
63185
raise NotImplementedError(
64186
"%s doesn't support System.from" % (self.__class__.__name__)
65187
)
66188

67189
def to_system(self, data, *args, **kwargs):
68-
"""System.to.
190+
"""Implement System.to that converts from System to this format.
69191
70192
Parameters
71193
----------
72194
data : dict
73-
system data
195+
system data, whose keys are defined in System.DTYPES
74196
*args : list
75-
other parameters
197+
arguments that will be passed from the method
76198
**kwargs : dict
77-
other parameters
199+
keyword arguments that will be passed from the method
78200
"""
79201
raise NotImplementedError(
80202
"%s doesn't support System.to" % (self.__class__.__name__)
81203
)
82204

83205
def from_labeled_system(self, file_name, **kwargs):
206+
"""Implement LabeledSystem.from that converts from this format to LabeledSystem.
207+
208+
Parameters
209+
----------
210+
file_name : str
211+
file name, i.e. the first argument
212+
**kwargs : dict
213+
keyword arguments that will be passed from the method
214+
215+
Returns
216+
-------
217+
data : dict
218+
system data, whose keys are defined in LabeledSystem.DTYPES
219+
"""
84220
raise NotImplementedError(
85221
"%s doesn't support LabeledSystem.from" % (self.__class__.__name__)
86222
)
87223

88224
def to_labeled_system(self, data, *args, **kwargs):
225+
"""Implement LabeledSystem.to that converts from LabeledSystem to this format.
226+
227+
By default, LabeledSystem.to will fallback to System.to.
228+
229+
Parameters
230+
----------
231+
data : dict
232+
system data, whose keys are defined in LabeledSystem.DTYPES
233+
*args : list
234+
arguments that will be passed from the method
235+
**kwargs : dict
236+
keyword arguments that will be passed from the method
237+
"""
89238
return self.to_system(data, *args, **kwargs)
90239

91240
def from_bond_order_system(self, file_name, **kwargs):
241+
"""Implement BondOrderSystem.from that converts from this format to BondOrderSystem.
242+
243+
Parameters
244+
----------
245+
file_name : str
246+
file name, i.e. the first argument
247+
**kwargs : dict
248+
keyword arguments that will be passed from the method
249+
250+
Returns
251+
-------
252+
data : dict
253+
system data
254+
"""
92255
raise NotImplementedError(
93256
"%s doesn't support BondOrderSystem.from" % (self.__class__.__name__)
94257
)
95258

96259
def to_bond_order_system(self, data, rdkit_mol, *args, **kwargs):
260+
"""Implement BondOrderSystem.to that converts from BondOrderSystem to this format.
261+
262+
By default, BondOrderSystem.to will fallback to LabeledSystem.to.
263+
264+
Parameters
265+
----------
266+
data : dict
267+
system data
268+
rdkit_mol : rdkit.Chem.rdchem.Mol
269+
rdkit mol object
270+
*args : list
271+
arguments that will be passed from the method
272+
**kwargs : dict
273+
keyword arguments that will be passed from the method
274+
"""
97275
return self.to_system(data, *args, **kwargs)
98276

99277
class MultiModes:
100-
"""File mode for MultiSystems
101-
0 (default): not implemented
102-
1: every directory under the top-level directory is a system.
278+
"""File mode for MultiSystems.
279+
280+
The current implemented modes are:
281+
282+
- 0 (default): not implemented
283+
- 1: every directory under the top-level directory is a system.
103284
"""
104285

105286
NotImplemented = 0
@@ -108,14 +289,16 @@ class MultiModes:
108289
MultiMode = MultiModes.NotImplemented
109290

110291
def from_multi_systems(self, directory, **kwargs):
111-
"""MultiSystems.from.
292+
"""Implement MultiSystems.from that converts from this format to MultiSystems.
293+
294+
By default, this method follows MultiMode to implement the conversion.
112295
113296
Parameters
114297
----------
115298
directory : str
116299
directory of system
117300
**kwargs : dict
118-
other parameters
301+
keyword arguments that will be passed from the method
119302
120303
Returns
121304
-------
@@ -133,6 +316,19 @@ def from_multi_systems(self, directory, **kwargs):
133316
)
134317

135318
def to_multi_systems(self, formulas, directory, **kwargs):
319+
"""Implement MultiSystems.to that converts from MultiSystems to this format.
320+
321+
By default, this method follows MultiMode to implement the conversion.
322+
323+
Parameters
324+
----------
325+
formulas : list[str]
326+
list of formulas
327+
directory : str
328+
directory of system
329+
**kwargs : dict
330+
keyword arguments that will be passed from the method
331+
"""
136332
if self.MultiMode == self.MultiModes.Directory:
137333
return [os.path.join(directory, ff) for ff in formulas]
138334
raise NotImplementedError(
@@ -149,7 +345,7 @@ def mix_system(self, *system, type_map, **kwargs):
149345
type_map : list of str
150346
Maps atom type to name
151347
**kwargs : dict
152-
other parameters
348+
keyword arguments that will be passed from the method
153349
154350
Returns
155351
-------

0 commit comments

Comments
 (0)