@@ -588,6 +588,95 @@ def unique_atoms(atoms):
588588 return unique
589589
590590
591+ def prioritize_coordinating_atoms_to_validate (
592+ gr_atoms_dict , sorted_gr_atoms , metal , ligand
593+ ):
594+ priority_atoms = []
595+
596+ group_formula = labels2formula (gr_atoms_dict ["labels" ])
597+
598+ def add_priority_atom (atom ):
599+ if atom not in priority_atoms :
600+ priority_atoms .append (atom )
601+
602+ if "Si" in gr_atoms_dict ["labels" ]:
603+ si_idx = gr_atoms_dict ["labels" ].index ("Si" )
604+ si_margin = gr_atoms_dict ["margins" ][si_idx ]
605+
606+ # Si priority: If Si is present and has a large margin, prioritize it for validation
607+ if si_margin > 0.25 :
608+ add_priority_atom (sorted_gr_atoms [si_idx ])
609+
610+ if "B" in gr_atoms_dict ["labels" ]:
611+ is_bh4_like = ligand .formula == "H4-B" or (
612+ gr_atoms_dict ["labels" ].count ("B" ) >= 1
613+ and gr_atoms_dict ["labels" ].count ("H" ) >= 2
614+ )
615+
616+ logger .debug (
617+ "Evaluating BH4-like priority: ligand formula %s, group formula %s, is_bh4_like=%s" ,
618+ ligand .formula ,
619+ group_formula ,
620+ is_bh4_like ,
621+ )
622+
623+ gr_atom_site_set = set (gr_atoms_dict ["atom_site_labels" ])
624+ excluded_neighbor_labels = {}
625+
626+ for atom in sorted_gr_atoms :
627+ if atom .label != "B" :
628+ continue
629+
630+ if is_bh4_like :
631+ add_priority_atom (atom )
632+ continue
633+
634+ adj_atoms = [
635+ ligand .get_parent ("molecule" ).atoms [adj ] for adj in atom .adjacency
636+ ]
637+
638+ local_neighbors = [
639+ adj
640+ for adj in adj_atoms
641+ if adj .atom_site_label in gr_atom_site_set
642+ and adj .label not in excluded_neighbor_labels
643+ ]
644+
645+ local_atoms = [atom ] + local_neighbors
646+ n_adj_in_gr_atoms = len (local_neighbors )
647+
648+ atom_margin = (
649+ np .linalg .norm (metal .coord - atom .coord ) - metal .radii - atom .radii
650+ )
651+
652+ max_local_margin = max (
653+ np .linalg .norm (metal .coord - local_atom .coord )
654+ - metal .radii
655+ - local_atom .radii
656+ for local_atom in local_atoms
657+ )
658+
659+ is_farthest_atom = np .isclose (atom_margin , max_local_margin )
660+
661+ logger .debug (
662+ "B atom %s: n_valid_neighbors=%d, local_neighbor_labels=%s, "
663+ "atom_margin=%.3f, max_local_margin=%.3f, is_farthest_atom=%s" ,
664+ atom .atom_site_label ,
665+ n_adj_in_gr_atoms ,
666+ [adj .label for adj in local_neighbors ],
667+ atom_margin ,
668+ max_local_margin ,
669+ is_farthest_atom ,
670+ )
671+
672+ # Prioritize B if at least two neighboring atoms are also coordinated
673+ if n_adj_in_gr_atoms >= 2 :
674+ add_priority_atom (atom )
675+ elif n_adj_in_gr_atoms == 1 and group_formula == "H-B" :
676+ add_priority_atom (atom )
677+ return priority_atoms
678+
679+
591680def validate_coordinated_atoms (gr_atoms , metal , ligand , haptic , removed_ligand_indices ):
592681 """
593682 Checks if atoms in gr_atoms are truly connected to the metal.
@@ -651,7 +740,6 @@ def validate_coordinated_atoms(gr_atoms, metal, ligand, haptic, removed_ligand_i
651740 gr_atoms_dict ["atom_site_labels" ] = None
652741
653742 # 2. Detailed Debug Logging
654- group_formula = labels2formula (gr_atoms_dict ["labels" ])
655743 logger .debug (
656744 "Sorted coordinated atoms (farthest first): %s" , gr_atoms_dict ["labels" ]
657745 )
@@ -661,11 +749,11 @@ def validate_coordinated_atoms(gr_atoms, metal, ligand, haptic, removed_ligand_i
661749 logger .debug ("Sorted coordinated atom distances: %s" , gr_atoms_dict ["distances" ])
662750 logger .debug ("Sorted coordinated atom margins: %s" , gr_atoms_dict ["margins" ])
663751
664- if haptic :
665- logger .debug (
666- "Haptic coordination detected. Skipping validation. %s" , group_formula
667- )
668- return gr_atoms , False
752+ # if haptic:
753+ # logger.debug(
754+ # "Haptic coordination detected. Skipping validation. %s", group_formula
755+ # )
756+ # return gr_atoms, False
669757
670758 # if "H" not in gr_atoms_labels:
671759 # outlier_atoms = find_atom_outlier(sorted_gr_atoms, metal, haptic)
@@ -675,37 +763,9 @@ def validate_coordinated_atoms(gr_atoms, metal, ligand, haptic, removed_ligand_i
675763 # logger.debug(
676764 # "Hydrogen atoms detected in coordination sphere. Prioritizing their validation."
677765 # )
678-
679- priority_atoms = []
680-
681- def add_priority_atom (atom ):
682- if atom not in priority_atoms :
683- priority_atoms .append (atom )
684-
685- # Si priority: If Si is present and has a large margin, prioritize it for validation
686- if "Si" in gr_atoms_dict ["labels" ]:
687- si_idx = gr_atoms_dict ["labels" ].index ("Si" )
688- si_margin = gr_atoms_dict ["margins" ][si_idx ]
689-
690- if si_margin > 0.25 :
691- add_priority_atom (sorted_gr_atoms [si_idx ])
692-
693- # BH4-like priority
694- is_bh4_like = ligand .formula == "H4-B" or (
695- gr_atoms_dict ["labels" ].count ("B" ) >= 1
696- and gr_atoms_dict ["labels" ].count ("H" ) >= 2
697- )
698- logger .debug (
699- "Evaluating BH4-like priority: ligand formula %s, group formula %s, %s" ,
700- ligand .formula ,
701- group_formula ,
702- is_bh4_like ,
766+ priority_atoms = prioritize_coordinating_atoms_to_validate (
767+ gr_atoms_dict , sorted_gr_atoms , metal , ligand
703768 )
704- if is_bh4_like :
705- for atom in sorted_gr_atoms :
706- if atom .label == "B" :
707- add_priority_atom (atom )
708-
709769 if priority_atoms :
710770 logger .debug (
711771 "Priority atoms identified for validation: %s %s" ,
0 commit comments