@@ -473,20 +473,25 @@ def _align_with_esp(self, mp_ref_and_relaxed: MoleculePair) -> float:
473473
474474 def _align_with_pharm (self , mp_ref_and_relaxed : MoleculePair ) -> float :
475475 """
476- Align relaxed molecule to reference/target molecule with pharmacophores
476+ Align relaxed molecule to reference/target molecule with pharmacophores.
477+
478+ Stores aligned fit anchors and vectors on ``self._aligned_pharm_ancs``
479+ and ``self._aligned_pharm_vecs`` for downstream subset scoring.
477480
478481 Returns
479482 -------
480483 float : Pharmacophore similarity score of optimally aligned molecule.
481484 """
482- aligned_fit_anchors , aligned_vectors = mp_ref_and_relaxed .align_with_pharm (
485+ aligned_fit_anchors , aligned_fit_vectors = mp_ref_and_relaxed .align_with_pharm (
483486 similarity = 'tanimoto' ,
484487 extended_points = False ,
485488 only_extended = False ,
486489 num_repeats = 1 ,
487490 trans_init = False ,
488491 use_jax = False
489492 )
493+ self ._aligned_pharm_ancs = aligned_fit_anchors
494+ self ._aligned_pharm_vecs = aligned_fit_vectors
490495 pharm_similarity = mp_ref_and_relaxed .sim_aligned_pharm
491496 return float (pharm_similarity )
492497
@@ -501,8 +506,10 @@ def __init__(self,
501506 condition : str ,
502507 num_surf_points : int = 400 ,
503508 pharm_multi_vector : Optional [bool ] = None ,
509+ priority_pharm_indices : Optional [list ] = None ,
504510 solvent : Optional [str ] = None ,
505- num_processes : int = 1 ):
511+ num_processes : int = 1 ,
512+ ):
506513 """
507514 Evaluation pipeline for conditionally-generated molecules.
508515
@@ -536,6 +543,15 @@ def __init__(self,
536543 Number of surface points to sample for similarity scoring. Default is 400.
537544 pharm_multi_vector : bool, optional
538545 Use multiple vectors to represent Aro/HBA/HBD or single.
546+ priority_pharm_indices : list of int, optional
547+ Indices (into ``ref_molec`` pharmacophore arrays) of "priority"
548+ pharmacophores. When provided, two additional Tversky
549+ (``'tversky_ref'``) scores are computed after the full-set pharm
550+ alignment: one for the priority subset and one for the non-priority
551+ complement subset, each scored against the full pharmacophore set
552+ of the aligned generated molecule. Requires ``condition`` to be
553+ ``'pharm'`` or ``'all'`` and ``pharm_multi_vector`` to be a bool.
554+ Must satisfy ``0 < len(priority_pharm_indices) < N_pharm``.
539555 solvent : str, optional
540556 Solvent type for xTB relaxation.
541557 num_processes : int, optional
@@ -574,6 +590,11 @@ def __init__(self,
574590 self .sim_surf_target_relax_esp_aligned = None
575591 self .sim_pharm_target_relax_esp_aligned = None
576592
593+ self .sim_pharm_priority_target_relax_optimal = None
594+ self .sim_pharm_nonpriority_target_relax_optimal = None
595+
596+ self .priority_pharm_indices = priority_pharm_indices
597+
577598 # Scoring parameters
578599 self .num_surf_points = num_surf_points
579600 self .alpha = ALPHA (self .num_surf_points ) # Fitted to probe_radius=1.2
@@ -674,6 +695,39 @@ def __init__(self,
674695 if (self .condition == 'pharm' or self .condition == 'all' ) and isinstance (pharm_multi_vector , bool ):
675696 self .sim_pharm_target_relax_optimal = self ._align_with_pharm (mp_ref_and_relaxed = mp_ref_and_relaxed )
676697
698+ # Priority subset Tversky scoring using the alignment from the full-set pharm alignment above
699+ if (self .priority_pharm_indices is not None
700+ and hasattr (self , '_aligned_pharm_ancs' )
701+ and self .ref_molec .pharm_ancs is not None ):
702+ n_pharm = len (self .ref_molec .pharm_types )
703+ nonpriority_indices = sorted (set (range (n_pharm )) - set (self .priority_pharm_indices ))
704+ priority_idx = self .priority_pharm_indices
705+
706+ self .sim_pharm_priority_target_relax_optimal = float (get_overlap_pharm_np (
707+ ptype_1 = self .ref_molec .pharm_types [priority_idx ],
708+ ptype_2 = self .molec_post_opt .pharm_types ,
709+ anchors_1 = self .ref_molec .pharm_ancs [priority_idx ],
710+ anchors_2 = self ._aligned_pharm_ancs ,
711+ vectors_1 = self .ref_molec .pharm_vecs [priority_idx ],
712+ vectors_2 = self ._aligned_pharm_vecs ,
713+ similarity = 'tversky_ref' ,
714+ extended_points = False ,
715+ only_extended = False
716+ ))
717+
718+ if nonpriority_indices :
719+ self .sim_pharm_nonpriority_target_relax_optimal = float (get_overlap_pharm_np (
720+ ptype_1 = self .ref_molec .pharm_types [nonpriority_indices ],
721+ ptype_2 = self .molec_post_opt .pharm_types ,
722+ anchors_1 = self .ref_molec .pharm_ancs [nonpriority_indices ],
723+ anchors_2 = self ._aligned_pharm_ancs ,
724+ vectors_1 = self .ref_molec .pharm_vecs [nonpriority_indices ],
725+ vectors_2 = self ._aligned_pharm_vecs ,
726+ similarity = 'tversky_ref' ,
727+ extended_points = False ,
728+ only_extended = False
729+ ))
730+
677731 # Compute ESP-aligned surf and pharmacophore similarity scores
678732 if mp_ref_and_relaxed .transform_esp is not None and self .condition in ('esp' , 'all' ):
679733 molec_post_opt_esp_aligned = mp_ref_and_relaxed .get_transformed_molecule (mp_ref_and_relaxed .transform_esp )
@@ -733,19 +787,24 @@ def _align_with_esp(self, mp_ref_and_relaxed: MoleculePair) -> float:
733787
734788 def _align_with_pharm (self , mp_ref_and_relaxed : MoleculePair ) -> float :
735789 """
736- Align relaxed molecule to reference/target molecule with pharmacophores
790+ Align relaxed molecule to reference/target molecule with pharmacophores.
791+
792+ Stores aligned fit anchors and vectors on ``self._aligned_pharm_ancs``
793+ and ``self._aligned_pharm_vecs`` for downstream subset scoring.
737794
738795 Returns
739796 -------
740797 float : Pharmacophore similarity score of optimally aligned molecule.
741798 """
742- aligned_fit_anchors , aligned_vectors = mp_ref_and_relaxed .align_with_pharm (
799+ aligned_fit_anchors , aligned_fit_vectors = mp_ref_and_relaxed .align_with_pharm (
743800 similarity = 'tanimoto' ,
744801 extended_points = False ,
745802 only_extended = False ,
746803 num_repeats = 1 ,
747804 trans_init = False ,
748805 use_jax = False
749806 )
807+ self ._aligned_pharm_ancs = aligned_fit_anchors
808+ self ._aligned_pharm_vecs = aligned_fit_vectors
750809 pharm_similarity = mp_ref_and_relaxed .sim_aligned_pharm
751810 return float (pharm_similarity )
0 commit comments