@@ -1053,6 +1053,116 @@ def uma_opt_batch_cmd(
10531053 click .echo (f"Error: { e } " , err = True )
10541054
10551055
1056+ # ==========================================
1057+ # PACMOF2 COMMANDS
1058+ # ==========================================
1059+ @main .group ("pacmof2" )
1060+ def pacmof2_cli ():
1061+ """Commands for PACMOF2 charge prediction."""
1062+ pass
1063+
1064+
1065+ @pacmof2_cli .command ("predict" )
1066+ @click .option (
1067+ "--cif" ,
1068+ default = None ,
1069+ type = click .Path (exists = True ),
1070+ help = "Path to a single CIF file." ,
1071+ )
1072+ @click .option (
1073+ "--cif-dir" ,
1074+ default = None ,
1075+ type = click .Path (exists = True , file_okay = False ),
1076+ help = "Directory containing CIF files." ,
1077+ )
1078+ @click .option (
1079+ "--outdir" ,
1080+ required = True ,
1081+ type = click .Path (),
1082+ help = "Output directory for CIFs with predicted charges." ,
1083+ )
1084+ @click .option (
1085+ "--identifier" ,
1086+ default = "_pacmof" ,
1087+ help = "Suffix for output filenames (default: _pacmof)." ,
1088+ )
1089+ @click .option (
1090+ "--net-charge" ,
1091+ default = "0" ,
1092+ help = "Net charge: integer for single MOF, or path to "
1093+ "JSON file mapping filenames to charges for batch." ,
1094+ )
1095+ @click .option (
1096+ "--adjust-method" ,
1097+ default = "mean" ,
1098+ type = click .Choice (["mean" , "magnitude" ]),
1099+ help = "Charge adjustment method." ,
1100+ )
1101+ def pacmof2_predict (
1102+ cif ,
1103+ cif_dir ,
1104+ outdir ,
1105+ identifier ,
1106+ net_charge ,
1107+ adjust_method ,
1108+ ):
1109+ """Predict partial atomic charges for CIF structures.
1110+
1111+ Provide either --cif for a single file or --cif-dir for
1112+ a directory of CIF files.
1113+
1114+ \b
1115+ Examples:
1116+ matkit pacmof2 predict --cif-dir cifs/ --outdir charged/
1117+ matkit pacmof2 predict --cif structure.cif --outdir charged/
1118+ matkit pacmof2 predict --cif-dir cifs/ --outdir charged/ \\
1119+ --net-charge charges.json
1120+ """
1121+ if cif and cif_dir :
1122+ click .echo (
1123+ "Error: specify --cif or --cif-dir, not both." ,
1124+ err = True ,
1125+ )
1126+ return
1127+ if not cif and not cif_dir :
1128+ click .echo ("Error: provide --cif or --cif-dir." , err = True )
1129+ return
1130+
1131+ cif_path = cif_dir if cif_dir else cif
1132+
1133+ # Parse net_charge: try int/float first, then JSON path
1134+ try :
1135+ nc = int (net_charge )
1136+ except ValueError :
1137+ try :
1138+ nc = float (net_charge )
1139+ except ValueError :
1140+ nc = net_charge # treat as JSON file path
1141+
1142+ try :
1143+ from matkit .pacmof2 import run_charge_prediction
1144+
1145+ result = run_charge_prediction (
1146+ cif_path = cif_path ,
1147+ output_dir = outdir ,
1148+ identifier = identifier ,
1149+ net_charge = nc ,
1150+ adjust_charge_method = adjust_method ,
1151+ )
1152+ click .echo (
1153+ f"Predicted charges for { result ['num_structures' ]} "
1154+ f"structure(s). Output: { result ['output_dir' ]} "
1155+ )
1156+ except ImportError :
1157+ click .echo (
1158+ "Error: pacmof2 is required. "
1159+ "Install with: pip install matkit[pacmof2]" ,
1160+ err = True ,
1161+ )
1162+ except Exception as e :
1163+ click .echo (f"Error: { e } " , err = True )
1164+
1165+
10561166# ==========================================
10571167# ZEOPP COMMANDS
10581168# ==========================================
0 commit comments