1+ #!/usr/bin/env python3
2+ """
3+ Convert legacy log format.
4+ """
5+
6+ import argparse
7+ import json
8+ import sys
9+ import tarfile
10+ from pathlib import Path
11+
12+ def consolidate_rounds (target_folder ):
13+ """
14+ Consolidate round results into metadata.json and archive rounds folder.
15+
16+ Args:
17+ target_folder (str): Path to the target experiment folder
18+ """
19+ target_path = Path (target_folder )
20+
21+ if not target_path .exists ():
22+ print (f"Error: Target folder '{ target_folder } ' does not exist" )
23+ return False
24+
25+ rounds_tar_path = target_path / "rounds.tar.gz"
26+
27+ # 1. Check if rounds.tar.gz already exists
28+ if rounds_tar_path .exists ():
29+ print (f"rounds.tar.gz already exists in '{ target_folder } ', skipping" )
30+ return True
31+
32+ # Check if rounds folder exists
33+ rounds_folder = target_path / "rounds"
34+ if not rounds_folder .exists ():
35+ print (f"Error: rounds folder does not exist in '{ target_folder } '" )
36+ return False
37+
38+ # Load existing metadata.json
39+ metadata_path = target_path / "metadata.json"
40+ if not metadata_path .exists ():
41+ print (f"Error: metadata.json does not exist in '{ target_folder } '" )
42+ return False
43+
44+ try :
45+ with open (metadata_path , 'r' ) as f :
46+ metadata = json .load (f )
47+ except json .JSONDecodeError as e :
48+ print (f"Error: Failed to parse metadata.json: { e } " )
49+ return False
50+
51+ # 2. Process each round folder and collect results
52+ round_stats = {}
53+
54+ # Find all round folders (rounds/0, rounds/1, etc.)
55+ round_folders = [d for d in rounds_folder .iterdir () if d .is_dir () and d .name .isdigit ()]
56+ round_folders .sort (key = lambda x : int (x .name ))
57+
58+ for round_folder in round_folders :
59+ round_num = int (round_folder .name )
60+ results_path = round_folder / "results.json"
61+
62+ if not results_path .exists ():
63+ print (f"Warning: results.json not found in { round_folder } , skipping" )
64+ continue
65+
66+ try :
67+ with open (results_path , 'r' ) as f :
68+ results = json .load (f )
69+
70+ # Extract the relevant data from results.json
71+ # Assuming results.json has the structure we need
72+ round_stats [str (round_num )] = {
73+ ** results # Include all data from results.json
74+ }
75+
76+ print (f"Processed round { round_num } " )
77+
78+ except json .JSONDecodeError as e :
79+ print (f"Error: Failed to parse results.json in round { round_num } : { e } " )
80+ continue
81+ except Exception as e :
82+ print (f"Error processing round { round_num } : { e } " )
83+ continue
84+
85+ if not round_stats :
86+ print ("Error: No valid round results found" )
87+ return False
88+
89+ # Update metadata with round_stats
90+ metadata ["round_stats" ] = round_stats
91+
92+ # Write updated metadata.json
93+ try :
94+ with open (metadata_path , 'w' ) as f :
95+ json .dump (metadata , f , indent = 2 )
96+ print (f"Updated metadata.json with { len (round_stats )} rounds" )
97+ except Exception as e :
98+ print (f"Error: Failed to write updated metadata.json: { e } " )
99+ return False
100+
101+ # 3. Create tar.gz archive of rounds folder
102+ try :
103+ print ("Creating rounds.tar.gz archive..." )
104+ with tarfile .open (rounds_tar_path , 'w:gz' ) as tar :
105+ tar .add (rounds_folder , arcname = 'rounds' )
106+
107+ print (f"Successfully created { rounds_tar_path } " )
108+
109+ # Optionally remove the original rounds folder after successful archiving
110+ # Uncomment the following lines if you want to delete the original folder:
111+ # shutil.rmtree(rounds_folder)
112+ # print("Removed original rounds folder")
113+
114+ except Exception as e :
115+ print (f"Error: Failed to create rounds.tar.gz: { e } " )
116+ return False
117+
118+ print (f"Successfully consolidated rounds for '{ target_folder } '" )
119+ return True
120+
121+ def main ():
122+ parser = argparse .ArgumentParser (
123+ description = "Consolidate round results into metadata.json and archive rounds folder"
124+ )
125+ parser .add_argument (
126+ "target_folders" ,
127+ nargs = "+" ,
128+ help = "Path(s) to the target experiment folder(s)"
129+ )
130+
131+ args = parser .parse_args ()
132+
133+ success_count = 0
134+ total_count = len (args .target_folders )
135+
136+ for target_folder in args .target_folders :
137+ print (f"\n Processing folder: { target_folder } " )
138+ success = consolidate_rounds (target_folder )
139+ if success :
140+ success_count += 1
141+ else :
142+ print (f"Failed to process folder: { target_folder } " )
143+
144+ print (f"\n Summary: { success_count } /{ total_count } folders processed successfully" )
145+
146+ if success_count < total_count :
147+ sys .exit (1 )
148+
149+ if __name__ == "__main__" :
150+ main ()
0 commit comments