@@ -50,7 +50,7 @@ def get_vector_dimension(xtal):
5050 return sum (len (site .get_bounds ()) for site in xtal .mol_sites )
5151
5252
53- def plot_id_vs_energy (code , energies , match_ids = None , match_energies = None , out_dir = "qrs_plots" ):
53+ def plot_id_vs_energy (code , energies , match_ids = None , match_energies = None , out_dir = "qrs_plots" , time_cost_s = None ):
5454 """Save a plot of visited-structure ID vs energy for one QRS run."""
5555 if not energies :
5656 print (f"No energies collected for { code } ; skipping plot." )
@@ -76,72 +76,81 @@ def plot_id_vs_energy(code, energies, match_ids=None, match_energies=None, out_d
7676 )
7777 ax .set_xlabel ("Visited Structure ID" )
7878 ax .set_ylabel ("Energy (kcal/mol)" )
79- ax .set_title (f"{ code } : visited structure ID vs energy" )
79+ if time_cost_s is not None :
80+ ax .set_title (f"{ code } : visited structure ID vs energy (time: { time_cost_s :.2f} s)" )
81+ else :
82+ ax .set_title (f"{ code } : visited structure ID vs energy" )
8083 ax .grid (alpha = 0.25 , linestyle = "--" , linewidth = 0.6 )
8184 ax .legend (loc = "best" )
85+ ax .set_ylim (min (energies ) - 5 , max (energies ) + 50 )
8286 fig .tight_layout ()
8387
8488 fig_path = os .path .join (out_dir , f"{ code } _id_vs_energy.png" )
8589 fig .savefig (fig_path , dpi = 200 )
8690 plt .close (fig )
8791 print (f"Saved plot: { fig_path } " )
8892
89- db = database ("pyxtal/database/test.db" )
90-
91- csv_path = "qrs_results.csv"
92- with open (csv_path , "w" , newline = "" ) as fcsv :
93- writer = csv .writer (fcsv )
94- writer .writerow (["code" , "smiles" , "sg" , "vector_dim" , "time_cost_s" , "success_rate" ])
95-
96- for code in db .get_all_codes ()[2 :]:
97- # ── Molecule ──────────────────────────────────────────────────────────────────
98- row = db .get_row (code = code )
99- ref_xtal = db .get_pyxtal (code = code )
100- if ref_xtal .has_special_site (): ref_xtal = ref_xtal .to_subgroup ()
101- vector_dim = get_vector_dimension (ref_xtal )
102- ref_pmg = ref_xtal .to_pymatgen ()
103- ref_pmg .remove_species (["H" ]) # ignore H for matching since positions are less certain
104- print (ref_xtal )
105-
106- sites = [[] for _ in range (len (ref_xtal .numMols ))]
107- for site in ref_xtal .mol_sites :
108- sites [site .type ].append (site .wp .get_label ())
109-
110- # ── QRS setup ─────────────────────────────────────────────────────────────────
111- qrs = QRS (
112- smiles = row .mol_smi , # molecule as SMILES string
113- workdir = row .csd_code , # working directory for this QRS run
114- sg = ref_xtal .group .hall_number , # space group number (P2_1/c = 81)
115- tag = row .csd_code .lower (), # tag for output files
116- use_hall = True , # interpret sg as a Hall number
117- lattice = ref_xtal .lattice , # fix the cell; only WP positions are sampled
118- N_gen = 10 , # number of QRS generations
119- N_pop = 50 , # structures per generation
120- N_cpu = 1 ,
121- cif = "all.cif" , # save all relaxed structures
122- skip_mlp = True , # no machine-learning potential relaxation
123- verbose = False ,
124- sites = sites ,
125- delta_length = 1.5 , # grid spacing for fractional coords (Å)
126- delta_angle = 60.0 , # grid spacing for Euler/torsion angles (°)
127- )
128-
129- # ── Run and check for match ───────────────────────────────────────────────────
130- t0 = perf_counter ()
131- success_rate = qrs .run (ref_pmg = ref_pmg )
132- time_cost_s = perf_counter () - t0
133-
134- if success_rate is not None and success_rate > 0 :
135- print (f"\n Match found! Success rate: { success_rate } %" )
136- else :
137- print ("\n No match found within the given generations/population." )
138- print (f"Time cost: { time_cost_s :.2f} s" )
139-
140- match_ids , match_energies = get_match_points (qrs )
141- plot_id_vs_energy (code , qrs .engs , match_ids , match_energies )
93+ if __name__ == "__main__" :
94+ db = database ("pyxtal/database/test.db" )
95+ os .makedirs ("Tests" , exist_ok = True )
96+ csv_path = "Tests/qrs_results.csv"
14297
143- with open (csv_path , "a " , newline = "" ) as fcsv :
98+ with open (csv_path , "w " , newline = "" ) as fcsv :
14499 writer = csv .writer (fcsv )
145- writer .writerow ([code , row .mol_smi , ref_xtal .group .number , vector_dim ,
146- f"{ time_cost_s :.2f} " ,
147- f"{ success_rate :.4f} " if success_rate is not None else "" ])
100+ writer .writerow (["code" , "smiles" , "sg" , "vector_dim" , "time_cost_s" , "success_rate" ])
101+
102+ for code in db .get_all_codes ()[4 :]:
103+ # ── Molecule ──────────────────────────────────────────────────────────────────
104+ row = db .get_row (code = code )
105+ ref_xtal = db .get_pyxtal (code = code )
106+ if ref_xtal .has_special_site (): ref_xtal = ref_xtal .to_subgroup ()
107+ vector_dim = get_vector_dimension (ref_xtal )
108+ ref_pmg = ref_xtal .to_pymatgen ()
109+ ref_pmg .remove_species (["H" ]) # ignore H for matching since positions are less certain
110+ print (ref_xtal )
111+ workdir = os .path .join ("Tests" , row .csd_code )
112+
113+ sites = [[] for _ in range (len (ref_xtal .numMols ))]
114+ for site in ref_xtal .mol_sites :
115+ sites [site .type ].append (site .wp .get_label ())
116+
117+ # ── QRS setup ─────────────────────────────────────────────────────────────────
118+ if os .path .exists (workdir + '/parameters.xml' ):
119+ os .remove (workdir + '/parameters.xml' )
120+ qrs = QRS (
121+ smiles = row .mol_smi , # molecule as SMILES string
122+ workdir = workdir , # working directory for this QRS run
123+ sg = ref_xtal .group .hall_number , # space group number (P2_1/c = 81)
124+ tag = row .csd_code .lower (), # tag for output files
125+ use_hall = True , # interpret sg as a Hall number
126+ lattice = ref_xtal .lattice , # fix the cell; only WP positions are sampled
127+ N_gen = 10 , # number of QRS generations
128+ N_pop = 50 , # structures per generation
129+ N_cpu = 2 ,
130+ cif = "all.cif" , # save all relaxed structures
131+ skip_mlp = True , # no machine-learning potential relaxation
132+ verbose = False ,
133+ sites = sites ,
134+ delta_length = 1.5 , # grid spacing for fractional coords (Å)
135+ delta_angle = 60.0 , # grid spacing for Euler/torsion angles (°)
136+ )
137+
138+ # ── Run and check for match ───────────────────────────────────────────────────
139+ t0 = perf_counter ()
140+ success_rate = qrs .run (ref_pmg = ref_pmg )
141+ time_cost_s = perf_counter () - t0
142+
143+ if success_rate is not None and success_rate > 0 :
144+ print (f"\n Match found! Success rate: { success_rate } %" )
145+ else :
146+ print ("\n No match found within the given generations/population." )
147+ print (f"Time cost: { time_cost_s :.2f} s" )
148+
149+ match_ids , match_energies = get_match_points (qrs )
150+ plot_id_vs_energy (code , qrs .engs , match_ids , match_energies , time_cost_s = time_cost_s )
151+
152+ with open (csv_path , "a" , newline = "" ) as fcsv :
153+ writer = csv .writer (fcsv )
154+ writer .writerow ([code , row .mol_smi , ref_xtal .group .number , vector_dim ,
155+ f"{ time_cost_s :.2f} " ,
156+ f"{ success_rate :.4f} " if success_rate is not None else "" ])
0 commit comments