From ef8b5ca4c2d086488077fc226d68b207696fc2d8 Mon Sep 17 00:00:00 2001 From: ConorFWild <41680328+ConorFWild@users.noreply.github.com> Date: Fri, 16 Feb 2024 15:05:38 +0000 Subject: [PATCH 1/7] Address m2m issue 1280 by ensuring conformer sites in only one canonical site --- .../generate_aligned_structures.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/ligand_neighbourhood_alignment/generate_aligned_structures.py b/src/ligand_neighbourhood_alignment/generate_aligned_structures.py index 76f1b0e9..3f279257 100644 --- a/src/ligand_neighbourhood_alignment/generate_aligned_structures.py +++ b/src/ligand_neighbourhood_alignment/generate_aligned_structures.py @@ -267,6 +267,7 @@ def _align_structure( _structure, moving_ligand_id: tuple[str, str, str], reference_ligand_id: tuple[str, str, str], + neighbourhood: dt.Neighbourhood, g, neighbourhood_transforms: dict[tuple[tuple[str, str, str], tuple[str, str, str]], dt.Transform], conformer_site_transforms: dict[tuple[str, str], dt.Transform], @@ -304,6 +305,13 @@ def _align_structure( _structure = superpose_structure(running_transform, _structure) + # Drop chains without atoms + neighbourhood_chains = set([_atom_id[0] for _atom_id in neighbourhood.atoms]) + for _model in _structure: + for _chain in _model: + if _chain.name not in neighbourhood_chains: + _structure.remove_chain(_chain.name) + # Write the fully aligned structure _structure.write_pdb(str(out_path)) From 047110c6723e4307dfd7ec4f59c42301b611572f Mon Sep 17 00:00:00 2001 From: ConorFWild <41680328+ConorFWild@users.noreply.github.com> Date: Fri, 16 Feb 2024 15:05:56 +0000 Subject: [PATCH 2/7] Removing non-binding chains from aligned output --- .../generate_aligned_structures.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ligand_neighbourhood_alignment/generate_aligned_structures.py b/src/ligand_neighbourhood_alignment/generate_aligned_structures.py index 3f279257..7687bd36 100644 --- a/src/ligand_neighbourhood_alignment/generate_aligned_structures.py +++ b/src/ligand_neighbourhood_alignment/generate_aligned_structures.py @@ -305,7 +305,7 @@ def _align_structure( _structure = superpose_structure(running_transform, _structure) - # Drop chains without atoms + # Drop chains without atoms in neighbourhood neighbourhood_chains = set([_atom_id[0] for _atom_id in neighbourhood.atoms]) for _model in _structure: for _chain in _model: From 883c6672c25ef50e3f853902295426683ddb475b Mon Sep 17 00:00:00 2001 From: ConorFWild <41680328+ConorFWild@users.noreply.github.com> Date: Fri, 16 Feb 2024 15:08:28 +0000 Subject: [PATCH 3/7] Removing non-binding chains from aligned output --- .../generate_sites_from_components.py | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/ligand_neighbourhood_alignment/generate_sites_from_components.py b/src/ligand_neighbourhood_alignment/generate_sites_from_components.py index fbb8dc20..7d8aa404 100644 --- a/src/ligand_neighbourhood_alignment/generate_sites_from_components.py +++ b/src/ligand_neighbourhood_alignment/generate_sites_from_components.py @@ -27,7 +27,8 @@ ) # from ligand_neighbourhood_alignment.save_sites import save_sites -from ligand_neighbourhood_alignment.structures import get_structures, get_transform_from_residues, _get_transform_from_residues +from ligand_neighbourhood_alignment.structures import get_structures, get_transform_from_residues, \ + _get_transform_from_residues def get_components(g): @@ -150,9 +151,9 @@ def get_sites_from_conformer_sites(conformer_sites: ConformerSites, neighbourhoo def get_xtalform_sites_from_canonical_sites( - canonical_sites: CanonicalSites, - assigned_xtalforms: AssignedXtalForms, - xtalforms: XtalForms, + canonical_sites: CanonicalSites, + assigned_xtalforms: AssignedXtalForms, + xtalforms: XtalForms, ): """ Each canonical site may occur in several forms, depending on the @@ -212,7 +213,6 @@ def get_xtalform_sites_from_canonical_sites( def get_subsite_transforms(sites: CanonicalSites, structures): - transforms = {} for site_id, site in zip(sites.site_ids, sites.sites): rss = site.reference_ligand_id.dtag @@ -227,21 +227,22 @@ def get_subsite_transforms(sites: CanonicalSites, structures): return transforms + from ligand_neighbourhood_alignment import dt + + def _update_conformer_site_transforms( - conformer_site_transforms, - canonical_site: dt.CanonicalSite, - conformer_sites: dict[str, dt.ConformerSite], + conformer_site_transforms, + canonical_site: dt.CanonicalSite, + conformer_sites: dict[str, dt.ConformerSite], structures, - ): - +): ref_conformer_site = conformer_sites[canonical_site.reference_conformer_site_id] ref_conformer_site_residues = ref_conformer_site.residues for conformer_site_id in canonical_site.conformer_site_ids: key = (canonical_site.reference_conformer_site_id, conformer_site_id) if key not in conformer_site_transforms: - conformer_site = conformer_sites[conformer_site_id] # conformer_site_residues = conformer_site.residues @@ -253,8 +254,6 @@ def _update_conformer_site_transforms( conformer_site_transforms[key] = dt.Transform(transform.vec.tolist(), transform.mat.tolist()) - - # transforms = {} # for site_id, site in zip(sites.site_ids, sites.sites): # rss = site.reference_ligand_id.dtag @@ -289,14 +288,15 @@ def get_site_transforms(sites: CanonicalSites, structures): return transforms + def _update_canonical_site_transforms( - canonical_site_transforms: dict[str, dt.Transform], + canonical_site_transforms: dict[str, dt.Transform], canonical_site_id, - canonical_site: dt.CanonicalSite, - # canonical_sites: dict[str, dt.CanonicalSite], + canonical_site: dt.CanonicalSite, + # canonical_sites: dict[str, dt.CanonicalSite], conformer_sites: dict[str, dt.ConformerSite], structures, - ): +): rss = structures[canonical_site.global_reference_dtag] ref_site_all_ress = [ (chain.name, res.seqid.num) for model in rss for chain in model for res in chain @@ -311,6 +311,7 @@ def _update_canonical_site_transforms( transform.mat.tolist(), ) + def _update_reference_structure_transforms( reference_structure_transforms, key, @@ -327,8 +328,8 @@ def _update_reference_structure_transforms( transform.mat.tolist(), ) -def _generate_sites_from_components(_source_dir: Path): +def _generate_sites_from_components(_source_dir: Path): logger.info(f"Source dir: {_source_dir}") g = read_graph(_source_dir) neighbourhoods: LigandNeighbourhoods = read_neighbourhoods(_source_dir) @@ -395,4 +396,3 @@ def _generate_sites_from_components(_source_dir: Path): save_site_transforms(site_transforms, _source_dir) return canonical_sites - From 4e208ec01b2e6abaaef3c8a54a7b4efb48a5ca04 Mon Sep 17 00:00:00 2001 From: ConorFWild <41680328+ConorFWild@users.noreply.github.com> Date: Mon, 19 Feb 2024 11:06:46 +0000 Subject: [PATCH 4/7] Sensible error for issue 1337 --- src/ligand_neighbourhood_alignment/cli.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/ligand_neighbourhood_alignment/cli.py b/src/ligand_neighbourhood_alignment/cli.py index 5a26c455..ac9cd860 100644 --- a/src/ligand_neighbourhood_alignment/cli.py +++ b/src/ligand_neighbourhood_alignment/cli.py @@ -521,7 +521,17 @@ def _generate_assembly( # op = gemmi.Op(generator.triplet) op = gemmi.Op(_transform) # chain_clone = structure[0][generator.chain].clone() - chain_clone = structure[0][_chain].clone() + try: + chain_clone = structure[0][_chain].clone() + except Exception as e: + raise Exception( + 'An Exception occurred in generating the biological assemblies\n' + f'Based on the assembly, the expected chains were: {xtalform_assembly.chains}\n' + f'However the chains in the structure were: {[_x.name for _x in structure[0]]}\n' + 'XCA does not currently handle datasets with a mis-match between the xtalform chains.\n' + 'You should ensure that the chain names are consistent with the reference dataset for the xtalforms.' + ) + for residue in chain_clone: for atom in residue: From f720240e92cec715a7e9597b22a801396e912b81 Mon Sep 17 00:00:00 2001 From: ConorFWild <41680328+ConorFWild@users.noreply.github.com> Date: Wed, 21 Feb 2024 10:22:49 +0000 Subject: [PATCH 5/7] Sensible error for issue 1337 --- src/ligand_neighbourhood_alignment/cli.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ligand_neighbourhood_alignment/cli.py b/src/ligand_neighbourhood_alignment/cli.py index ac9cd860..490550cb 100644 --- a/src/ligand_neighbourhood_alignment/cli.py +++ b/src/ligand_neighbourhood_alignment/cli.py @@ -532,7 +532,6 @@ def _generate_assembly( 'You should ensure that the chain names are consistent with the reference dataset for the xtalforms.' ) - for residue in chain_clone: for atom in residue: atom_frac = structure.cell.fractionalize(atom.pos) From ff41f5d3fc053115248a265bb7bb3926c1d5f16f Mon Sep 17 00:00:00 2001 From: ConorFWild <41680328+ConorFWild@users.noreply.github.com> Date: Wed, 21 Feb 2024 10:33:46 +0000 Subject: [PATCH 6/7] Sensible error for issue 1337 --- src/ligand_neighbourhood_alignment/cli.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ligand_neighbourhood_alignment/cli.py b/src/ligand_neighbourhood_alignment/cli.py index 490550cb..128b3bd0 100644 --- a/src/ligand_neighbourhood_alignment/cli.py +++ b/src/ligand_neighbourhood_alignment/cli.py @@ -1292,6 +1292,7 @@ def _update( _structure, moving_ligand_id, reference_ligand_id, + ligand_neighbourhoods[moving_ligand_id], alignability_graph, ligand_neighbourhood_transforms, conformer_site_transforms, From 9f3757ad0547be581312e5493330540253d04d79 Mon Sep 17 00:00:00 2001 From: ConorFWild <41680328+ConorFWild@users.noreply.github.com> Date: Wed, 21 Feb 2024 10:35:54 +0000 Subject: [PATCH 7/7] Sensible error for issue 1337 --- .../generate_aligned_structures.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ligand_neighbourhood_alignment/generate_aligned_structures.py b/src/ligand_neighbourhood_alignment/generate_aligned_structures.py index 7687bd36..7f03f412 100644 --- a/src/ligand_neighbourhood_alignment/generate_aligned_structures.py +++ b/src/ligand_neighbourhood_alignment/generate_aligned_structures.py @@ -310,7 +310,7 @@ def _align_structure( for _model in _structure: for _chain in _model: if _chain.name not in neighbourhood_chains: - _structure.remove_chain(_chain.name) + _model.remove_chain(_chain.name) # Write the fully aligned structure _structure.write_pdb(str(out_path))