1010
1111
1212class JobStatus (StrEnum ):
13+ """Enumeration of possible job statuses for VASP calculations."""
14+
1315 PENDING = "PENDING"
1416 DONE = "DONE"
1517 NOT_CONVERGED = "NOT_CONVERGED"
1618
1719
1820class FolderClassifier :
21+ """Classifies VASP calculation folders by job status and provides summary and filtering utilities."""
22+
1923 def __init__ (self , details ):
24+ """
25+ Args:
26+ details (dict): Dictionary mapping folder names to job status details.
27+ """
2028 self ._details = details
2129
2230 @classmethod
2331 def from_directory (cls , root = "." , atol = 1e-6 ):
32+ """
33+ Scan a directory for VASP calculation folders and classify their job status.
34+
35+ Args:
36+ root (str): Root directory to scan. Defaults to current directory.
37+ atol (float): Absolute tolerance for force convergence. Defaults to 1e-6.
38+
39+ Returns:
40+ FolderClassifier: An instance with details populated from the directory.
41+ """
2442 details = {}
2543 for folder in sorted (os .listdir (root )):
2644 folder_path = os .path .join (root , folder )
@@ -58,6 +76,12 @@ def from_directory(cls, root=".", atol=1e-6):
5876
5977 @property
6078 def summary (self ):
79+ """
80+ Compute the fraction of jobs in each status.
81+
82+ Returns:
83+ dict: Mapping of job status to fraction of jobs in that status.
84+ """
6185 status_list = [v ["status" ] for v in self ._details .values ()]
6286 total = len (status_list )
6387 counter = Counter (status_list )
@@ -68,15 +92,39 @@ def summary(self):
6892
6993 @property
7094 def details (self ):
95+ """
96+ Get the raw details dictionary.
97+
98+ Returns:
99+ dict: Folder details with job status, force sum, and reason.
100+ """
71101 return self ._details
72102
73103 def list_pending (self ):
104+ """
105+ List folders with PENDING status.
106+
107+ Returns:
108+ list: Folder names with status PENDING.
109+ """
74110 return [k for k , v in self .details .items () if v ["status" ] == JobStatus .PENDING ]
75111
76112 def list_done (self ):
113+ """
114+ List folders with DONE status.
115+
116+ Returns:
117+ list: Folder names with status DONE.
118+ """
77119 return [k for k , v in self .details .items () if v ["status" ] == JobStatus .DONE ]
78120
79121 def list_incomplete (self ):
122+ """
123+ List folders with NOT_CONVERGED status.
124+
125+ Returns:
126+ list: Folder names with status NOT_CONVERGED.
127+ """
80128 return [
81129 k for k , v in self .details .items () if v ["status" ] == JobStatus .NOT_CONVERGED
82130 ]
0 commit comments