Skip to content

Commit 57a487d

Browse files
committed
Fix CE-Symm bug relating to short subunits.
[rcsb/symmetry#118](rcsb/symmetry#118) The problem was actually downstream from CE-Symm in the QuatSymmDetector code used for assigning a symmetry group. The code was re-aligning subunits using CE. This fails for short alignments of <15 residues (two AFP with default settings). Thus no atoms get aligned and an exception was thrown whenever an output format required information about the symmetry group. This fix re-uses the original CE-Symm alignment for the symmetry group detection. This might change CE-Symm and QuatSymm results for proteins with small subunits or borderline scores. Changes: - New `SubunitClustererMethod.MANUAL` enum value - Improve `SymmetryTools.getQuaternarySymmetry`
1 parent e9e0f00 commit 57a487d

File tree

4 files changed

+74
-11
lines changed

4 files changed

+74
-11
lines changed

biojava-structure/src/main/java/org/biojava/nbio/structure/align/multiple/util/MultipleAlignmentTools.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
import org.biojava.nbio.structure.align.multiple.BlockSet;
5858
import org.biojava.nbio.structure.align.multiple.MultipleAlignment;
5959
import org.biojava.nbio.structure.align.util.AlignmentTools;
60+
import org.biojava.nbio.structure.cluster.SubunitCluster;
6061
import org.biojava.nbio.structure.jama.Matrix;
6162
import org.forester.evoinference.matrix.distance.BasicSymmetricalDistanceMatrix;
6263
import org.forester.phylogeny.Phylogeny;
@@ -964,4 +965,46 @@ public static Phylogeny getStructuralTree(MultipleAlignment msta) {
964965
return tree;
965966
}
966967

968+
/**
969+
* Convert an MSA into a matrix of equivalent residues.
970+
*
971+
* This concatenates all blocks, meaning that the indices might not be
972+
* sequential.
973+
*
974+
* Indices should be consistent with `msa.getAtomArrays()`.
975+
* @param msa Multiple alignment
976+
* @param coreOnly Include only core (ungapped) columns. Otherwise gaps are
977+
* represented with null.
978+
* @return
979+
*/
980+
public static List<List<Integer>> getEquivalentResidues(MultipleAlignment msa, boolean coreOnly) {
981+
List<List<Integer>> eqr = new ArrayList<>();
982+
for (int str = 0; str < msa.size(); str++) {
983+
eqr.add(new ArrayList<>());
984+
}
985+
986+
for(Block block: msa.getBlocks()) {
987+
List<List<Integer>> aln = block.getAlignRes();
988+
for (int col = 0; col < block.length(); col++) {
989+
// skip non-core columns
990+
if(coreOnly) {
991+
boolean core = true;
992+
for (int str = 0; str < block.size(); str++) {
993+
if (aln.get(str).get(col) == null) {
994+
core = false;
995+
break;
996+
}
997+
}
998+
if(!core) {
999+
continue;
1000+
}
1001+
}
1002+
// add column to eqr
1003+
for (int str = 0; str < block.size(); str++) {
1004+
eqr.get(str).add(aln.get(str).get(col));
1005+
}
1006+
}
1007+
}
1008+
return eqr;
1009+
}
9671010
}

biojava-structure/src/main/java/org/biojava/nbio/structure/cluster/SubunitCluster.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,22 @@ public SubunitCluster(SubunitCluster other, List<Integer> subunitsToRetain) {
158158
setAlpha(other.getAlpha());
159159
}
160160

161+
/**
162+
* Create the cluster manually by specifying subunits and the equivalent residues
163+
* @param subunits List of aligned subunits
164+
* @param subunitEQR Double list giving the aligned residue indices in each subunit
165+
*/
166+
public SubunitCluster(List<Subunit> subunits, List<List<Integer>> subunitEQR) {
167+
if(subunits.size() != subunitEQR.size()) {
168+
throw new IllegalArgumentException("Mismatched subunit length");
169+
}
170+
this.subunits = subunits;
171+
this.subunitEQR = subunitEQR;
172+
this.representative = 0;
173+
this.method = SubunitClustererMethod.MANUAL;
174+
this.pseudoStoichiometric = false;
175+
}
176+
161177
/**
162178
* Subunits contained in the SubunitCluster.
163179
*

biojava-structure/src/main/java/org/biojava/nbio/structure/cluster/SubunitClustererMethod.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ public enum SubunitClustererMethod {
5959
* sequence and structure clustering differ, the cluster contains
6060
* pseudosymmetry (by definition).
6161
*/
62-
SEQUENCE_STRUCTURE
63-
}
62+
SEQUENCE_STRUCTURE,
6463

64+
/**
65+
* Some other method was used when clustering.
66+
*/
67+
MANUAL,
68+
}

biojava-structure/src/main/java/org/biojava/nbio/structure/symmetry/utils/SymmetryTools.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,18 @@
5353
import org.biojava.nbio.structure.align.multiple.MultipleAlignmentImpl;
5454
import org.biojava.nbio.structure.align.multiple.util.CoreSuperimposer;
5555
import org.biojava.nbio.structure.align.multiple.util.MultipleAlignmentScorer;
56+
import org.biojava.nbio.structure.align.multiple.util.MultipleAlignmentTools;
5657
import org.biojava.nbio.structure.align.multiple.util.MultipleSuperimposer;
5758
import org.biojava.nbio.structure.cluster.Subunit;
59+
import org.biojava.nbio.structure.cluster.SubunitCluster;
5860
import org.biojava.nbio.structure.cluster.SubunitClustererMethod;
5961
import org.biojava.nbio.structure.cluster.SubunitClustererParameters;
6062
import org.biojava.nbio.structure.geometry.SuperPositions;
6163
import org.biojava.nbio.structure.jama.Matrix;
6264
import org.biojava.nbio.structure.symmetry.core.QuatSymmetryDetector;
6365
import org.biojava.nbio.structure.symmetry.core.QuatSymmetryParameters;
6466
import org.biojava.nbio.structure.symmetry.core.QuatSymmetryResults;
67+
import org.biojava.nbio.structure.symmetry.core.Stoichiometry;
6568
import org.biojava.nbio.structure.symmetry.internal.CeSymmResult;
6669
import org.biojava.nbio.structure.symmetry.internal.SymmetryAxes;
6770
import org.jgrapht.Graph;
@@ -706,21 +709,18 @@ public static QuatSymmetryResults getQuaternarySymmetry(CeSymmResult result)
706709
throws StructureException {
707710

708711
// Obtain the subunits of the repeats
709-
List<Atom[]> atoms = toRepeatsAlignment(result).getAtomArrays();
712+
MultipleAlignment msa = toRepeatsAlignment(result);
713+
List<Atom[]> atoms = msa.getAtomArrays();
710714
List<Subunit> subunits = atoms.stream()
711715
.map(a -> new Subunit(a, null, null, null))
712716
.collect(Collectors.toList());
713-
714-
// The clustering thresholds are set to 0 so that all always merged
715-
SubunitClustererParameters cp = new SubunitClustererParameters();
716-
cp.setClustererMethod(SubunitClustererMethod.STRUCTURE);
717-
cp.setRMSDThreshold(10.0);
718-
cp.setStructureCoverageThreshold(0.0);
717+
List<List<Integer>> eqr = MultipleAlignmentTools.getEquivalentResidues(msa, true);
718+
SubunitCluster cluster = new SubunitCluster(subunits, eqr);
719+
Stoichiometry composition = new Stoichiometry(Arrays.asList(cluster));
719720

720721
QuatSymmetryParameters sp = new QuatSymmetryParameters();
721-
722722
QuatSymmetryResults gSymmetry = QuatSymmetryDetector
723-
.calcGlobalSymmetry(subunits, sp, cp);
723+
.calcGlobalSymmetry(composition, sp);
724724

725725
return gSymmetry;
726726
}

0 commit comments

Comments
 (0)