@@ -2181,7 +2181,7 @@ def add_atom_to_xyz_using_internal_coords(xyz: Union[dict, str],
21812181 a_value : float ,
21822182 d_value : float ,
21832183 opt_method : str = 'Nelder-Mead' ,
2184- ) -> Optional [dict ]:
2184+ ) -> Tuple [ Optional [dict ], Optional [ dict ] ]:
21852185 """
21862186 Add an atom to XYZ. The new atom may have random r, a, and d index parameters
21872187 (not necessarily defined for the same respective atoms).
@@ -2200,11 +2200,19 @@ def add_atom_to_xyz_using_internal_coords(xyz: Union[dict, str],
22002200 opt_method (str, optional): The optimization method to use for finding the new atom's coordinates.
22012201 Additional options include 'trust-constr' and 'BFGS'.
22022202
2203- Returns:
2204- Optional[dict]: The updated xyz coordinates.
2203+ Returns:
2204+ xyz_guess: Optional[dict]
2205+ The updated xyz coordinates dictionary if successful, None if no solution found
2206+ deviations: Optional[dict]
2207+ A dictionary of precision deviations if criteria weren't met:
2208+ {
2209+ 'distance': {'index': tuple, 'desired': float, 'error': float}, # distance error in Angstroms
2210+ 'angle': {'indices': tuple, 'desired': float, 'error': float}, # angle error in degrees
2211+ 'dihedral': {'indices': tuple, 'desired': float, 'error': float} # dihedral error in degrees
2212+ }
2213+ Returns None if precision criteria were met or no solution found.
22052214 """
22062215 xyz = check_xyz_dict (xyz )
2207-
22082216 def calculate_errors (result_coords ):
22092217 r_error = np .abs (np .sqrt (np .sum ((np .array (result_coords ) - np .array (xyz ['coords' ][r_index ]))** 2 )) - r_value )
22102218 a_error = np .sqrt (angle_constraint (xyz ['coords' ][a_indices [0 ]], xyz ['coords' ][a_indices [1 ]], a_value )(* result_coords ))
@@ -2213,7 +2221,7 @@ def calculate_errors(result_coords):
22132221
22142222 def meets_precision (result_coords ):
22152223 r_error , a_error , d_error = calculate_errors (result_coords )
2216- return r_error < 0.01 and a_error < 0.1 and d_error < 0.1
2224+ return r_error < 0.1 and a_error < 0.05236 and d_error < 0.05236
22172225
22182226 guess_functions = [
22192227 generate_initial_guess_r_a ,
@@ -2249,22 +2257,44 @@ def meets_precision(result_coords):
22492257
22502258 if meets_precision (new_coord ):
22512259 print ("Precision criteria met. Returning result." )
2252- return updated_xyz
2260+ return updated_xyz , None
22532261
22542262 if total_error < closest_error :
22552263 print (f"Updating closest result. Previous closest_error={ closest_error } , new total_error={ total_error } " )
22562264 closest_result = updated_xyz
2265+ closest_errors = (r_error , a_error , d_error )
22572266 closest_error = total_error
22582267
22592268 except Exception as e :
22602269 print (f"Attempt { attempt } with { guess_func .__name__ } failed due to exception: { e } " )
22612270
22622271 if closest_result is not None :
2263- print ("Returning closest result as no guess met precision criteria." )
2264- return closest_result
2272+ r_error , a_error , d_error = closest_errors
2273+ print (d_indices )
2274+ deviations = {}
2275+ last_index = len (updated_xyz ['coords' ]) - 1
2276+ if r_error >= 0.1 :
2277+ deviations ['distance' ] = {
2278+ 'index' : (r_index , last_index ),
2279+ 'desired' : r_value ,
2280+ 'error' : r_error
2281+ }
2282+ if a_error >= 0.05236 :
2283+ deviations ['angle' ] = {
2284+ 'indices' : (a_indices [0 ], a_indices [1 ], last_index ),
2285+ 'desired' : a_value ,
2286+ 'error' : np .degrees (a_error )
2287+ }
2288+ if d_error >= 0.05236 :
2289+ deviations ['dihedral' ] = {
2290+ 'indices' : (d_indices [0 ], d_indices [1 ], d_indices [2 ], last_index ),
2291+ 'desired' : np .degrees (d_value ),
2292+ 'error' : np .degrees (d_error )
2293+ }
2294+ return closest_result , deviations
22652295
22662296 print ("No valid solution was found." )
2267- return None
2297+ return None , None
22682298
22692299
22702300def _add_atom_to_xyz_using_internal_coords (xyz : dict ,
0 commit comments