def test_ca_atoms(self, structure_klifs_id, klifs_session, n_ca_atoms, n_ca_atoms_wo_na): """ Test the class property regarding the pocket's CA atoms, i.e. `ca_atoms`. """ pocket_bp = PocketBioPython.from_structure_klifs_id( structure_klifs_id, klifs_session) # Test property ca_atoms # Shape assert pocket_bp.ca_atoms.shape == (n_ca_atoms, 3) assert pocket_bp.ca_atoms.dropna(axis=0, subset=["residue.id"]).shape == ( n_ca_atoms_wo_na, 3, ) # Columns and dtypes assert pocket_bp.ca_atoms.columns.to_list() == [ "residue.id", "ca.atom", "ca.vector" ] assert pocket_bp.ca_atoms.dtypes.to_list() == [ "Int32", "object", "object" ] for ca_atom in pocket_bp.ca_atoms["ca.atom"]: if ca_atom: assert isinstance(ca_atom, Bio.PDB.Atom.Atom) for ca_vector in pocket_bp.ca_atoms["ca.vector"]: if ca_vector: assert isinstance(ca_vector, Bio.PDB.vectors.Vector)
def test_hse_ca_cb( self, structure_klifs_id, klifs_session, n_hse_ca_complex, n_hse_cb_complex, n_hse_ca_pocket, n_hse_cb_pocket, ): """ Test class - attributes (`_hse_ca_complex`, `_hse_cb_complex`) and - properties (`hse_ca`, `hse_cb`) regarding the HSExposure. """ pocket_bp = PocketBioPython.from_structure_klifs_id( structure_klifs_id, klifs_session) # HSE for full complex assert isinstance(pocket_bp._hse_ca_complex, Bio.PDB.HSExposure.HSExposureCA) assert len(pocket_bp._hse_ca_complex) == n_hse_ca_complex assert isinstance(pocket_bp._hse_cb_complex, Bio.PDB.HSExposure.HSExposureCB) assert len(pocket_bp._hse_cb_complex) == n_hse_cb_complex # HSE for pocket only assert isinstance(pocket_bp.hse_ca, dict) assert len(pocket_bp.hse_ca) == n_hse_ca_pocket assert isinstance(pocket_bp.hse_cb, dict) assert len(pocket_bp.hse_cb) == n_hse_cb_pocket
def test_get_physicochemical_or_spatial_features_dict( self, structure_klifs_id): """ Test if physicochemical an spatial features dictionary has correct keys. """ pocket_bp = PocketBioPython.from_structure_klifs_id( structure_klifs_id, LOCAL) pocket_df = PocketDataFrame.from_structure_klifs_id( structure_klifs_id, LOCAL) fingerprint = Fingerprint() # Physicochemical features physicochemical_dict = fingerprint._get_physicochemical_features_dict( pocket_bp) assert isinstance(physicochemical_dict, dict) assert list( physicochemical_dict.keys()) == FEATURE_NAMES_PHYSICOCHEMICAL_DICT # Spatial features spatial_dict = fingerprint._get_spatial_features_dict(pocket_df) assert isinstance(spatial_dict, dict) assert list(spatial_dict.keys()) == FEATURE_NAMES_SPATIAL_DICT assert list(spatial_dict["distances"].keys() ) == FEATURE_NAMES_DISTANCES_AND_MOMENTS assert list(spatial_dict["moments"].keys() ) == FEATURE_NAMES_DISTANCES_AND_MOMENTS
def test_from_pocket(self, structure_klifs_id, klifs_session): """ Test if SolventExposureFeature can be set from a Pocket object. Test object attribues. """ pocket = PocketBioPython.from_structure_klifs_id( structure_klifs_id, klifs_session) feature = SolventExposureFeature.from_pocket(pocket) assert isinstance(feature, SolventExposureFeature) # Test class attributes assert feature.name == structure_klifs_id for residue_id, residue_ix, ratio, ratio_ca, ratio_cb in zip( feature._residue_ids, feature._residue_ixs, feature._ratio, feature._ratio_ca, feature._ratio_cb, ): if residue_id is not None: assert isinstance(residue_id, int) assert isinstance(residue_ix, int) assert isinstance(ratio, float) assert isinstance(ratio_ca, float) assert isinstance(ratio_cb, float)
def test_side_chain_representatives(self, structure_klifs_id, klifs_session): """ Test the class property regarding the pocket's side chain representatives, i.e. `side_chain_representatives`. """ pocket_bp = PocketBioPython.from_structure_klifs_id( structure_klifs_id, klifs_session) assert isinstance(pocket_bp.side_chain_representatives, pd.DataFrame) # Test property side_chain_representatives # Columns and dtypes assert pocket_bp.side_chain_representatives.columns.to_list() == [ "residue.id", "sc.atom", "sc.vector", ] assert pocket_bp.side_chain_representatives.dtypes.to_list() == [ "Int32", "object", "object", ] for sc_atom in pocket_bp.side_chain_representatives["sc.atom"]: if sc_atom is not None: assert isinstance(sc_atom, Bio.PDB.Atom.Atom) for sc_vector in pocket_bp.side_chain_representatives["sc.vector"]: if sc_vector is not None: assert isinstance(sc_vector, Bio.PDB.vectors.Vector)
def test_from_pocket(self, structure_klifs_id, klifs_session): """ Test if SideChainOrientationFeature can be set from a Pocket object. Test object attribues. """ pocket = PocketBioPython.from_structure_klifs_id( structure_klifs_id, klifs_session) feature = SideChainOrientationFeature.from_pocket(pocket) assert isinstance(feature, SideChainOrientationFeature) # Test class attributes assert feature.name == structure_klifs_id for residue_id, residue_ix, category, vertex_angle, ca_atom, sc_atom in zip( feature._residue_ids, feature._residue_ixs, feature._categories, feature._vertex_angles, feature._ca_atoms, feature._sc_atoms, ): if residue_id is not None: assert isinstance(residue_id, int) assert isinstance(residue_ix, int) assert isinstance(category, float) assert isinstance(vertex_angle, float) if ca_atom is not None: assert isinstance(ca_atom, Bio.PDB.vectors.Vector) if sc_atom: assert isinstance(sc_atom, Bio.PDB.vectors.Vector) assert isinstance(feature._pocket_center, Bio.PDB.vectors.Vector)
def test_from_pocket_raises(self, structure_klifs_id, klifs_session, feature_name): """ Test if SiteAlignFeature raises error when passed an invalid feature name. """ with pytest.raises(KeyError): pocket = PocketBioPython.from_structure_klifs_id( structure_klifs_id, klifs_session=klifs_session) SiteAlignFeature.from_pocket(pocket, feature_name)
def test_get_exposure_by_method(self, structure_klifs_id, klifs_session, radius, method, n_residues, up_mean, down_mean): """ Test half sphere exposure and exposure ratio calculation as well as the result format. Parameters ---------- structure_klifs_id : int KLIFS structure ID. klifs_session : opencadd.databases.klifs.session.Session KLIFS session. radius : float Sphere radius to be used for half sphere exposure calculation. method : str Half sphere exposure method name: HSExposureCA or HSExposureCB. n_residues : int Number of residues in exposure calculation result. up_mean : float Mean of all exposure up values. down_mean : float Mean of all exposure down values. """ # Calculate exposure pocket = PocketBioPython.from_structure_klifs_id( structure_klifs_id, klifs_session) exposures_calculated = SolventExposureFeature._get_exposures_by_method( pocket, radius, method) # Test DataFrame length assert len(exposures_calculated) == n_residues # Test column names prefix = method[-2:].lower() columns = [ f"{prefix}.{i}" for i in ["up", "down", "angle_cb_ca_pcb", "exposure"] ] assert list(exposures_calculated.columns) == columns # Test exposure up values (mean) up_mean_calculated = exposures_calculated[f"{prefix}.up"].mean() assert up_mean == pytest.approx(up_mean_calculated) # Test exposure down values (mean) down_mean_calculated = exposures_calculated[f"{prefix}.down"].mean() assert down_mean == pytest.approx(down_mean_calculated) # Test for example residue the exposure ratio calculation example_residue = exposures_calculated.iloc[0] ratio = example_residue[f"{prefix}.exposure"] ratio_calculated = example_residue[f"{prefix}.down"] / ( example_residue[f"{prefix}.up"] + example_residue[f"{prefix}.down"]) assert ratio == pytest.approx(ratio_calculated)
def test_values(self, structure_klifs_id, klifs_session, values_mean): """ Test class property: values. The mean refers to the mean of non-NaN values. """ pocket = PocketBioPython.from_structure_klifs_id( structure_klifs_id, klifs_session) feature = SideChainOrientationFeature.from_pocket(pocket) assert isinstance(feature.values, list) values_mean_calculated = pd.Series(feature.values).dropna().mean() assert values_mean == pytest.approx(values_mean_calculated)
def test_pcb_atom_from_gly_valueerror(self, structure_klifs_id, klifs_session, residue_id): """ Test exceptions in pseudo-CB calculation for GLY, i.e. method `_pcb_atom_from_gly`. """ pocket_bp = PocketBioPython.from_structure_klifs_id( structure_klifs_id, klifs_session) residue = pocket_bp._residue_from_residue_id(residue_id) with pytest.raises(ValueError): pocket_bp._pcb_atom_from_gly(residue)
def test_pcb_atom_from_non_gly(self, structure_klifs_id, klifs_session, residue_id): """ Test that this method will not be used for GLY. """ pocket_bp = PocketBioPython.from_structure_klifs_id( structure_klifs_id, klifs_session) residue = pocket_bp._residue_from_residue_id(residue_id) with pytest.raises(ValueError): pocket_bp._pcb_atom_from_non_gly(residue)
def test_values(self, structure_klifs_id, klifs_session): """ Test class property: values. """ pocket = PocketBioPython.from_structure_klifs_id( structure_klifs_id, klifs_session=klifs_session) # Use example feature type feature = SiteAlignFeature.from_pocket(pocket, feature_name="hba") assert isinstance(feature.values, list) for value in feature.values: assert isinstance(value, float)
def test_center(self, structure_klifs_id, klifs_session, pocket_centroid_mean): """ Test the class property regarding the pocket centroid, i.e. `center`. """ pocket_bp = PocketBioPython.from_structure_klifs_id( structure_klifs_id, klifs_session) # Test property center assert isinstance(pocket_bp.center, Bio.PDB.vectors.Vector) assert pocket_bp.center.get_array().mean() == pytest.approx( pocket_centroid_mean)
def test_data_complex(self, structure_klifs_id, klifs_session, n_atoms_complex, n_atoms_pocket): """ Test class attribute handling the complex data, i.e. `_data_complex`. """ pocket_bp = PocketBioPython.from_structure_klifs_id( structure_klifs_id, klifs_session) # Complex data assert isinstance(pocket_bp._data_complex, Bio.PDB.Chain.Chain) assert len(list( pocket_bp._data_complex.get_atoms())) == n_atoms_complex
def test_pcb_atom_from_gly(self, structure_klifs_id, klifs_session, residue_id, pcb_atom_mean): """ Test pseudo-CB calculation for GLY, i.e. method `_pcb_atom_from_gly`. """ pocket_bp = PocketBioPython.from_structure_klifs_id( structure_klifs_id, klifs_session) residue = pocket_bp._residue_from_residue_id(residue_id) # Check pCB atom mean pcb_atom_calculated = pocket_bp._pcb_atom_from_gly(residue) pcb_atom_mean_calculated = pcb_atom_calculated.get_array().mean() assert pcb_atom_mean == pytest.approx(pcb_atom_mean_calculated)
def from_text(cls, text, extension, residue_ids, residue_ixs, structure_name, kinase_name): """ Calculate fingerprint for a KLIFS structure (by complex data as text and pocket residue IDs and indices). Parameters ---------- text : str Structural complex data as string (file content). extension : str Structural complex data format (file extension). residue_ids : list of int Pocket residue IDs. residue_ixs : list of int Pocket residue indices. structure_name : str # TODO or structure_klifs_id? Structure name. kinase_name : str Kinase name. Returns ------- kissim.encoding.Fingerprint Fingerprint. """ # BioPython-based and DataFrame-based pocket are both necessary for fingerprint features pocket_bp = PocketBioPython.from_text( text, extension, residue_ids, residue_ixs, structure_name ) pocket_df = PocketDataFrame.from_text( text, extension, residue_ids, residue_ixs, structure_name ) if pocket_bp is None or pocket_df is None: logger.warning(f"{structure_name}: Empty fingerprint (pocket unaccessible).") fingerprint = None else: fingerprint = cls() fingerprint.structure_klifs_id = structure_name fingerprint.kinase_name = kinase_name fingerprint.residue_ids = pocket_bp._residue_ids fingerprint.residue_ixs = pocket_bp._residue_ixs values_dict = {} values_dict["physicochemical"] = fingerprint._get_physicochemical_features_dict( pocket_bp ) values_dict["spatial"] = fingerprint._get_spatial_features_dict(pocket_df) fingerprint.values_dict = values_dict return fingerprint
def test_details(self, structure_klifs_id, klifs_session): """ Test class property: details. """ pocket = PocketBioPython.from_structure_klifs_id( structure_klifs_id, klifs_session=klifs_session) # Use example feature type feature = SiteAlignFeature.from_pocket(pocket, feature_name="hba") assert isinstance(feature.details, pd.DataFrame) assert feature.details.columns.to_list() == [ "residue.id", "residue.name", "sitealign.category", ]
def test_pcb_atom(self, structure_klifs_id, klifs_session, residue_id, pcb_atom): """ Test pseudo-CB calculation for a residue, i.e. method `_pcb_atom`. """ pocket_bp = PocketBioPython.from_structure_klifs_id( structure_klifs_id, klifs_session) pcb_atom_calculated = pocket_bp._pcb_atom(residue_id) if pcb_atom is None: assert pcb_atom_calculated is None else: pcb_atom_calculated = pcb_atom_calculated.get_array() assert pcb_atom[0] == pytest.approx(pcb_atom_calculated[0]) assert pcb_atom[1] == pytest.approx(pcb_atom_calculated[1]) assert pcb_atom[2] == pytest.approx(pcb_atom_calculated[2])
def test_details(self, structure_klifs_id, klifs_session): """ Test class property: details. """ pocket = PocketBioPython.from_structure_klifs_id( structure_klifs_id, klifs_session) feature = SideChainOrientationFeature.from_pocket(pocket) assert isinstance(feature.details, pd.DataFrame) assert feature.details.columns.to_list() == [ "residue.id", "sco.category", "sco.angle", "ca.vector", "sc.vector", "pocket_center.vector", ] assert feature.details.index.to_list() == feature._residue_ixs
def test_ca_atom(self, structure_klifs_id, klifs_session, residue_id, ca_atom_mean): """ Test if CA atom is retrieved correctly from a residue ID (test if-else cases), i.e. `_ca_atom` method. """ pocket_bp = PocketBioPython.from_structure_klifs_id( structure_klifs_id, klifs_session) ca_atom_calculated = pocket_bp._ca_atom(residue_id) # Check CA atom mean if ca_atom_mean: assert isinstance(ca_atom_calculated, Bio.PDB.Atom.Atom) ca_atom_mean_calculated = ca_atom_calculated.get_vector( ).get_array().mean() assert ca_atom_mean == pytest.approx(ca_atom_mean_calculated) else: assert ca_atom_mean == ca_atom_calculated
def test_pcb_atoms(self, structure_klifs_id, klifs_session): """ Test the class property regarding the pocket's pCB atoms, i.e. `pcb_atoms`. """ pocket_bp = PocketBioPython.from_structure_klifs_id( structure_klifs_id, klifs_session) # Test property pcb_atoms # Shape assert pocket_bp.pcb_atoms.shape == (85, 2) # Columns and dtypes assert pocket_bp.pcb_atoms.columns.to_list() == [ "residue.id", "pcb.vector" ] assert pocket_bp.pcb_atoms.dtypes.to_list() == ["Int32", "object"] for pcb_vector in pocket_bp.pcb_atoms["pcb.vector"]: if pcb_vector is not None: assert isinstance(pcb_vector, Bio.PDB.vectors.Vector)
def test_side_chain_representative(self, structure_klifs_id, klifs_session, residue_id, sc_atom_mean): """ Test if side chain representative is retrieved correctly from a residue, i.e. method `_side_chain_representative`. """ pocket_bp = PocketBioPython.from_structure_klifs_id( structure_klifs_id, klifs_session) sc_atom_calculated = pocket_bp._side_chain_representative(residue_id) # Check side chain representative mean if sc_atom_mean is not None: assert isinstance(sc_atom_calculated, Bio.PDB.Atom.Atom) sc_atom_mean_calculated = sc_atom_calculated.get_vector( ).get_array().mean() assert sc_atom_mean == pytest.approx(sc_atom_mean_calculated) else: assert sc_atom_calculated == None
def test_details(self, structure_klifs_id, klifs_session): """ Test class property: details. """ pocket = PocketBioPython.from_structure_klifs_id( structure_klifs_id, klifs_session) feature = SolventExposureFeature.from_pocket(pocket) # Test DataFrame shape, columns, indices assert isinstance(feature.details, pd.DataFrame) assert feature.details.columns.to_list() == [ "residue.id", "exposure.category", "exposure.ratio", "exposure.ratio_ca", "exposure.ratio_cb", ] assert feature.details.index.to_list() == feature._residue_ixs
def test_get_exposures(self, structure_klifs_id, klifs_session, radius, n_residues, missing_exposure): """ Test join of HSExposureCA and HSExposureCB data. Parameters ---------- structure_klifs_id : int KLIFS structure ID. klifs_session : opencadd.databases.klifs.session.Session KLIFS session. radius : float Sphere radius to be used for half sphere exposure calculation. n_residues : int Number of residues in exposure calculation result. missing_exposure : dict of list of int Residue IDs with missing exposures for HSExposureCA and HSExposureCB calculation. """ # Get exposure pocket = PocketBioPython.from_structure_klifs_id( structure_klifs_id, klifs_session) feature = SolventExposureFeature() exposures_calculated = feature._get_exposures(pocket, radius) # Test DataFrame length assert len(exposures_calculated) == n_residues # Test column names column_names_ca = [ "ca.up", "ca.down", "ca.angle_cb_ca_pcb", "ca.exposure" ] column_names_cb = [ "cb.up", "cb.down", "cb.angle_cb_ca_pcb", "cb.exposure" ] column_names = column_names_ca + column_names_cb + ["exposure"] assert list(exposures_calculated.columns) == column_names # Test missing residues in HSExposureCA and HSExposureCB calculation assert (exposures_calculated[exposures_calculated["ca.exposure"].isna( )].index.to_list() == missing_exposure["ca"]) assert (exposures_calculated[exposures_calculated["cb.exposure"].isna( )].index.to_list() == missing_exposure["cb"])
def test_from_pocket(self, structure_klifs_id, klifs_session, feature_name): """ Test if SiteAlignFeature can be set from a Pocket object. Test object attribues. """ pocket = PocketBioPython.from_structure_klifs_id( structure_klifs_id, klifs_session=klifs_session) feature = SiteAlignFeature.from_pocket(pocket, feature_name) assert isinstance(feature, SiteAlignFeature) # Test class attributes assert feature.name == structure_klifs_id for residue_id, residue_ix, residue_name, category in zip( feature._residue_ids, feature._residue_ixs, feature._residue_names, feature._categories): if residue_id is not None: assert isinstance(residue_id, int) assert isinstance(residue_ix, int) assert isinstance(feature_name, str) assert isinstance(category, float)