Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public class MenuCreator {
* Menus included:
* <ul><li>File: open, save, export, import, exit.
* <li>Align: new pairwise alignment, new multiple alignment.
* <li>View: aligment panel, aligned pairs, text format,
* <li>View: alignment panel, aligned pairs, text format,
* FatCat format, distance matrices, dot plot.
* <li>Help
* </ul>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,15 @@ else if (pos < ca.length) {
return lst;
}

/**
* @deprecated Replace with {@see showMultipleAlignmentPanel}
*/
@Deprecated
public static void showMultipleAligmentPanel(MultipleAlignment multAln,
AbstractAlignmentJmol jmol) throws StructureException {
showMultipleAlignmentPanel(multAln, jmol);
}

/**
* Creates a new Frame with the MultipleAlignment Sequence Panel.
* The panel can communicate with the Jmol 3D visualization by
Expand All @@ -102,7 +111,7 @@ else if (pos < ca.length) {

* @throws StructureException
*/
public static void showMultipleAligmentPanel(MultipleAlignment multAln,
public static void showMultipleAlignmentPanel(MultipleAlignment multAln,
AbstractAlignmentJmol jmol) throws StructureException {

MultipleAligPanel me = new MultipleAligPanel(multAln, jmol);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
* and from a Jmol view an XML format is saved.
*
* @author Aleix Lafita
* @version 2.0 - adapted for MultipleAligments
* @version 2.0 - adapted for MultipleAlignments
*
*/
public class MySaveFileListener implements ActionListener {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ public void actionPerformed(ActionEvent ae) {
.showAlignmentImage(multAln, result);

} else if (cmd.equals(MenuCreator.ALIGNMENT_PANEL)) {
MultipleAlignmentJmolDisplay.showMultipleAligmentPanel(multAln,
MultipleAlignmentJmolDisplay.showMultipleAlignmentPanel(multAln,
this);

} else if (cmd.equals(MenuCreator.FATCAT_TEXT)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -684,7 +684,8 @@ private String drawSymmetryAxes() {
return s.toString();
}

private Vector3d getAligmentVector(Point3d point, Vector3d axis) {

private Vector3d getAlignmentVector(Point3d point, Vector3d axis) {
// for system with a single Cn axis
if (rotationGroup.getPointGroup().startsWith("C") || rotationGroup.getPointGroup().startsWith("D")) {
// if axis is orthogonal to principal axis, use principal axis as reference axis
Expand Down Expand Up @@ -760,14 +761,14 @@ private String getSymmetryAxis(int i, int j, String pointGroup, int n, Vector3d
if (drawPolygon) {
double polygonRadius = getMeanExtension() * 0.06;
if (n == 2) {
referenceAxis = getAligmentVector(p1, axis);
referenceAxis = getAlignmentVector(p1, axis);
s.append(getC2PolygonJmol(i, p1, referenceAxis, axis, color, polygonRadius, name));
referenceAxis = getAligmentVector(p2, axis);
referenceAxis = getAlignmentVector(p2, axis);
s.append(getC2PolygonJmol(j, p2, referenceAxis, axis, color, polygonRadius, name));
} else if (n > 2) {
referenceAxis = getAligmentVector(p1, axis);
referenceAxis = getAlignmentVector(p1, axis);
s.append(getPolygonJmol(i, p1, referenceAxis, axis, n, color, polygonRadius, name));
referenceAxis = getAligmentVector(p2, axis);
referenceAxis = getAlignmentVector(p2, axis);
s.append(getPolygonJmol(j, p2, referenceAxis, axis, n, color, polygonRadius, name));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,8 @@ public interface Block extends ScoresCache {

/**
* Calculates and returns the first position of the specified structure in
* the alignment that is not null. This will return the aligment index, not
* the reisude aligned in that position.
* the alignment that is not null. This will return the alignment index, not
* the residue aligned in that position.
*
* @param str
* structure index
Expand All @@ -148,8 +148,8 @@ public interface Block extends ScoresCache {

/**
* Calculates and returns the last position of the specified structure in
* the alignment that is not null. This will return the aligment index, not
* the reisude aligned in that position.
* the alignment that is not null. This will return the alignment index, not
* the residue aligned in that position.
*
* @param str
* structure index
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ private void initialize() throws StructureException {
}
}

// Set the superposition and score for the seed aligment
// Set the superposition and score for the seed alignment
checkGaps();
msa.clear();
imposer.superimpose(msa);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
import org.biojava.nbio.structure.align.multiple.BlockSet;
import org.biojava.nbio.structure.align.multiple.MultipleAlignment;
import org.biojava.nbio.structure.align.util.AlignmentTools;
import org.biojava.nbio.structure.cluster.SubunitCluster;
import org.biojava.nbio.structure.jama.Matrix;
import org.forester.evoinference.matrix.distance.BasicSymmetricalDistanceMatrix;
import org.forester.phylogeny.Phylogeny;
Expand Down Expand Up @@ -721,7 +722,7 @@ public static List<Atom[]> transformAtoms(MultipleAlignment alignment) {

/**
* Calculate a List of alignment indicies that correspond to the core of a
* Block, which means that all structures have a residue in that positon.
* Block, which means that all structures have a residue in that position.
*
* @param block
* alignment Block
Expand Down Expand Up @@ -964,4 +965,46 @@ public static Phylogeny getStructuralTree(MultipleAlignment msta) {
return tree;
}

/**
* Convert an MSA into a matrix of equivalent residues.
*
* This concatenates all blocks, meaning that the indices might not be
* sequential.
*
* Indices should be consistent with `msa.getAtomArrays()`.
* @param msa Multiple alignment
* @param coreOnly Include only core (ungapped) columns. Otherwise gaps are
* represented with null.
* @return
*/
public static List<List<Integer>> getEquivalentResidues(MultipleAlignment msa, boolean coreOnly) {
List<List<Integer>> eqr = new ArrayList<>();
for (int str = 0; str < msa.size(); str++) {
eqr.add(new ArrayList<>());
}

for(Block block: msa.getBlocks()) {
List<List<Integer>> aln = block.getAlignRes();
for (int col = 0; col < block.length(); col++) {
// skip non-core columns
if(coreOnly) {
boolean core = true;
for (int str = 0; str < block.size(); str++) {
if (aln.get(str).get(col) == null) {
core = false;
break;
}
}
if(!core) {
continue;
}
}
// add column to eqr
for (int str = 0; str < block.size(); str++) {
eqr.get(str).add(aln.get(str).get(col));
}
}
}
return eqr;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,22 @@ public SubunitCluster(SubunitCluster other, List<Integer> subunitsToRetain) {
setAlpha(other.getAlpha());
}

/**
* Create the cluster manually by specifying subunits and the equivalent residues
* @param subunits List of aligned subunits
* @param subunitEQR Double list giving the aligned residue indices in each subunit
*/
public SubunitCluster(List<Subunit> subunits, List<List<Integer>> subunitEQR) {
if(subunits.size() != subunitEQR.size()) {
throw new IllegalArgumentException("Mismatched subunit length");
}
this.subunits = subunits;
this.subunitEQR = subunitEQR;
this.representative = 0;
this.method = SubunitClustererMethod.MANUAL;
this.pseudoStoichiometric = false;
}

/**
* Subunits contained in the SubunitCluster.
*
Expand Down Expand Up @@ -496,6 +512,12 @@ public boolean mergeStructure(SubunitCluster other, SubunitClustererParameters p
other.subunits.get(other.representative)
.getRepresentativeAtoms());

if (afp.getOptLength() < 1) {
// alignment failed (eg if chains were too short)
throw new StructureException(
String.format("Subunits failed to align using %s", params.getSuperpositionAlgorithm()));
}

// Convert AFPChain to MultipleAlignment for convenience
MultipleAlignment msa = new MultipleAlignmentEnsembleImpl(
afp,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ public enum SubunitClustererMethod {
* sequence and structure clustering differ, the cluster contains
* pseudosymmetry (by definition).
*/
SEQUENCE_STRUCTURE
}
SEQUENCE_STRUCTURE,

/**
* Some other method was used when clustering.
*/
MANUAL,
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ public QuatSymmetrySubunits(List<SubunitCluster> clusters) {
clusterIds.add(c);
Atom[] atoms = clusters.get(c).getAlignedAtomsSubunit(s);

if( atoms.length == 0) {
throw new IllegalArgumentException("No aligned atoms in subunit");
}

Point3d[] points = Calc.atomsToPoints(atoms);

caCoords.add(points);
Expand Down Expand Up @@ -213,7 +217,7 @@ private void run() {
calcOriginalCenters();
calcCentroid();
calcCenters();
calcMomentsOfIntertia();
calcMomentsOfInertia();
}

private void calcOriginalCenters() {
Expand Down Expand Up @@ -272,7 +276,7 @@ public Point3d getUpperBound() {
return upper;
}

private void calcMomentsOfIntertia() {
private void calcMomentsOfInertia() {
for (Point3d[] trace : caCoords) {
for (Point3d p : trace) {
momentsOfInertia.addPoint(p, 1.0f);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public class SymmOptimizer {
private List<Double> mcScoreHistory;

/**
* Constructor with a seed MultipleAligment storing a refined symmetry
* Constructor with a seed MultipleAlignment storing a refined symmetry
* alignment of the repeats. To perform the optimization use the call or
* optimize methods after instantiation.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,18 @@
import org.biojava.nbio.structure.align.multiple.MultipleAlignmentImpl;
import org.biojava.nbio.structure.align.multiple.util.CoreSuperimposer;
import org.biojava.nbio.structure.align.multiple.util.MultipleAlignmentScorer;
import org.biojava.nbio.structure.align.multiple.util.MultipleAlignmentTools;
import org.biojava.nbio.structure.align.multiple.util.MultipleSuperimposer;
import org.biojava.nbio.structure.cluster.Subunit;
import org.biojava.nbio.structure.cluster.SubunitCluster;
import org.biojava.nbio.structure.cluster.SubunitClustererMethod;
import org.biojava.nbio.structure.cluster.SubunitClustererParameters;
import org.biojava.nbio.structure.geometry.SuperPositions;
import org.biojava.nbio.structure.jama.Matrix;
import org.biojava.nbio.structure.symmetry.core.QuatSymmetryDetector;
import org.biojava.nbio.structure.symmetry.core.QuatSymmetryParameters;
import org.biojava.nbio.structure.symmetry.core.QuatSymmetryResults;
import org.biojava.nbio.structure.symmetry.core.Stoichiometry;
import org.biojava.nbio.structure.symmetry.internal.CeSymmResult;
import org.biojava.nbio.structure.symmetry.internal.SymmetryAxes;
import org.jgrapht.Graph;
Expand Down Expand Up @@ -706,21 +709,18 @@ public static QuatSymmetryResults getQuaternarySymmetry(CeSymmResult result)
throws StructureException {

// Obtain the subunits of the repeats
List<Atom[]> atoms = toRepeatsAlignment(result).getAtomArrays();
MultipleAlignment msa = toRepeatsAlignment(result);
List<Atom[]> atoms = msa.getAtomArrays();
List<Subunit> subunits = atoms.stream()
.map(a -> new Subunit(a, null, null, null))
.collect(Collectors.toList());

// The clustering thresholds are set to 0 so that all always merged
SubunitClustererParameters cp = new SubunitClustererParameters();
cp.setClustererMethod(SubunitClustererMethod.STRUCTURE);
cp.setRMSDThreshold(10.0);
cp.setStructureCoverageThreshold(0.0);
List<List<Integer>> eqr = MultipleAlignmentTools.getEquivalentResidues(msa, true);
SubunitCluster cluster = new SubunitCluster(subunits, eqr);
Stoichiometry composition = new Stoichiometry(Arrays.asList(cluster));

QuatSymmetryParameters sp = new QuatSymmetryParameters();

QuatSymmetryResults gSymmetry = QuatSymmetryDetector
.calcGlobalSymmetry(subunits, sp, cp);
.calcGlobalSymmetry(composition, sp);

return gSymmetry;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

import static org.junit.Assert.*;
import static org.junit.Assume.assumeNotNull;
import static org.junit.jupiter.api.Assertions.assertNotNull;

import java.io.IOException;
import java.io.InputStream;
Expand Down Expand Up @@ -60,7 +61,7 @@ public void testEasyCases() throws IOException, StructureException {
CeSymmResult result = CeSymm.analyze(atoms);

assertTrue(result.isSignificant());
assertEquals(result.getNumRepeats(), orders[i]);
assertEquals(orders[i], result.getNumRepeats());
}
}

Expand All @@ -75,4 +76,26 @@ public void testAlphafold() throws IOException, StructureException {
CeSymmResult result = CeSymm.analyze(atoms);
assertNotNull(result);
}

@Test
public void testShort() throws IOException, StructureException {
// ERIC2_c35200, a near-perfect 15 residue beta-solenoid
// At 15 residues this should reliably trigger rcsb/symmetry#118
URL url = this.getClass().getResource("/AF-V9WDR2-F1-model_v4.cif");
assumeNotNull(url);
String file = url.getPath();
Structure s = StructureIO.getStructure(file);
assertNull(s.getPdbId());
Atom[] atoms = StructureTools.getRepresentativeAtomArray(s);
CESymmParameters params = new CESymmParameters();
params.setMinCoreLength(10); // Ensure it gets refined (should be 15 long)
CeSymmResult result = CeSymm.analyze(atoms, params);
assertNotNull(result);
assertTrue(result.isSignificant());
assertEquals(9, result.getNumRepeats());
assertEquals("H",result.getSymmGroup());
assertNotNull(result.getAxes());
assertNotEquals("Error", result.getReason());

}
}
Loading