Skip to content

Commit 05c6c35

Browse files
committed
Port CeSymm for internal symmetry detection code to BioJava
1 parent f9d0480 commit 05c6c35

File tree

19 files changed

+5209
-0
lines changed

19 files changed

+5209
-0
lines changed
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package org.biojava.nbio.structure.symmetry.gui;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
6+
import org.biojava.nbio.structure.Atom;
7+
import org.biojava.nbio.structure.Structure;
8+
import org.biojava.nbio.structure.StructureException;
9+
import org.biojava.nbio.structure.StructureTools;
10+
import org.biojava.nbio.structure.align.gui.AlignmentCalculationRunnable;
11+
import org.biojava.nbio.structure.align.gui.jmol.MultipleAlignmentJmol;
12+
import org.biojava.nbio.structure.align.multiple.MultipleAlignment;
13+
import org.biojava.nbio.structure.symmetry.internal.CESymmParameters;
14+
import org.biojava.nbio.structure.symmetry.internal.CeSymm;
15+
import org.slf4j.Logger;
16+
import org.slf4j.LoggerFactory;
17+
18+
/**
19+
* Calculates a symmetry analysis and displays the results.
20+
* Linked to the SymmetryGUI.
21+
* Does not generalize, uses CeSymm class directly to allow
22+
* for the symmetry axis recovery.
23+
*
24+
* @author Aleix Lafita
25+
*
26+
*/
27+
public class SymmetryCalc implements AlignmentCalculationRunnable {
28+
29+
private static final Logger logger =
30+
LoggerFactory.getLogger(SymmetryCalc.class);
31+
32+
boolean interrupted = false;
33+
34+
private String name;
35+
private Structure structure;
36+
private SymmetryGui parent;
37+
38+
/** Requests for a structure to analyze.
39+
*/
40+
public SymmetryCalc(SymmetryGui p, Structure s, String n) {
41+
parent = p;
42+
structure = s;
43+
name = n;
44+
}
45+
46+
@Override
47+
public void run() {
48+
49+
//The structure has been downloaded, now calculate the alignment ...
50+
CeSymm algorithm = parent.getSymmetryAlgorithm();
51+
CESymmParameters params = (CESymmParameters) algorithm.getParameters();
52+
53+
try {
54+
55+
List<Atom[]> atoms = new ArrayList<Atom[]>();
56+
atoms.add(StructureTools.getRepresentativeAtomArray(structure));
57+
58+
MultipleAlignment msa = algorithm.align(atoms);
59+
60+
List<String> names = new ArrayList<String>();
61+
for (int su=0; su<msa.size(); su++){
62+
names.add(name);
63+
}
64+
msa.getEnsemble().setStructureNames(names);
65+
66+
MultipleAlignmentJmol jmol =
67+
SymmetryDisplay.display(msa, algorithm.getSymmetryAxes());
68+
String title = jmol.getTitle();
69+
70+
if (params != null)
71+
title += " | OrderDetector=" + params.getOrderDetectorMethod()+
72+
" Refiner: "+params.getRefineMethod();
73+
jmol.setTitle(title);
74+
75+
} catch (StructureException e){
76+
logger.warn(e.getMessage());
77+
}
78+
parent.notifyCalcFinished();
79+
}
80+
81+
@Override
82+
public void interrupt() {
83+
interrupted = true;
84+
}
85+
86+
@Override
87+
public void cleanup() {
88+
89+
parent.notifyCalcFinished();
90+
parent = null;
91+
structure = null;
92+
}
93+
94+
@Override
95+
public void setNrCPUs(int useNrCPUs) {}
96+
}
Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
1+
package org.biojava.nbio.structure.symmetry.gui;
2+
3+
import java.awt.event.KeyEvent;
4+
import java.util.ArrayList;
5+
import java.util.List;
6+
7+
import javax.swing.JMenu;
8+
import javax.swing.JMenuBar;
9+
import javax.swing.JMenuItem;
10+
import javax.vecmath.Matrix4d;
11+
import javax.vecmath.Point3d;
12+
13+
import org.biojava.nbio.structure.*;
14+
import org.biojava.nbio.structure.align.gui.MultipleAlignmentDisplay;
15+
import org.biojava.nbio.structure.align.gui.jmol.MultipleAlignmentJmol;
16+
import org.biojava.nbio.structure.align.multiple.MultipleAlignment;
17+
import org.biojava.nbio.structure.align.multiple.util.MultipleAlignmentTools;
18+
import org.biojava.nbio.structure.align.util.RotationAxis;
19+
import org.biojava.nbio.structure.symmetry.core.AxisAligner;
20+
import org.biojava.nbio.structure.symmetry.core.QuatSymmetryDetector;
21+
import org.biojava.nbio.structure.symmetry.core.QuatSymmetryParameters;
22+
import org.biojava.nbio.structure.symmetry.core.QuatSymmetryResults;
23+
import org.biojava.nbio.structure.symmetry.core.Subunits;
24+
import org.biojava.nbio.structure.symmetry.internal.SymmetryAxes;
25+
import org.biojava.nbio.structure.symmetry.jmolScript.JmolSymmetryScriptGenerator;
26+
import org.biojava.nbio.structure.symmetry.jmolScript.JmolSymmetryScriptGeneratorPointGroup;
27+
import org.biojava.nbio.structure.symmetry.utils.SymmetryTools;
28+
29+
/**
30+
* Class that provides visualizations methods for symmetry
31+
* alignments. Call the display() method for the default
32+
* visualization of symmetry.
33+
*
34+
* @author Aleix Lafita
35+
*
36+
*/
37+
public class SymmetryDisplay {
38+
39+
/**
40+
* Displays a multiple alignment of the symmetry subunits.
41+
*
42+
* @param msa the symmetry multiple alignment obtained from CeSymm
43+
* @throws StructureException
44+
*/
45+
public static MultipleAlignmentJmol displaySubunits(MultipleAlignment msa)
46+
throws StructureException {
47+
48+
MultipleAlignment subunits = SymmetryTools.toSubunitAlignment(msa);
49+
return MultipleAlignmentDisplay.display(subunits);
50+
}
51+
52+
/**
53+
* Displays a multiple alignment of the whole structure transformations
54+
* colored by blocks, corresponding to the subunits.
55+
*
56+
* @param msa the symmetry multiple alignment obtained from CeSymm
57+
* @throws StructureException
58+
*/
59+
public static MultipleAlignmentJmol displayFull(MultipleAlignment msa)
60+
throws StructureException {
61+
62+
MultipleAlignment full = SymmetryTools.toFullAlignment(msa);
63+
64+
MultipleAlignmentJmol jmol = MultipleAlignmentDisplay.display(full);
65+
jmol.setColorByBlocks(true);
66+
67+
return jmol;
68+
}
69+
70+
/**
71+
* Displays a single structure in a cartoon representation with each
72+
* symmetric subunit colored differently.
73+
*
74+
* @param msa the symmetry multiple alignment obtained from CeSymm
75+
* @param axes symmetry axes
76+
* @throws StructureException
77+
*/
78+
public static MultipleAlignmentJmol display(MultipleAlignment msa,
79+
SymmetryAxes axes) throws StructureException {
80+
81+
List<Atom[]> atoms = msa.getAtomArrays();
82+
83+
MultipleAlignmentJmol jmol = new MultipleAlignmentJmol(msa, atoms);
84+
85+
addSymmetryMenu(jmol, axes);
86+
87+
//Show all the axes and point group symmetry
88+
if (axes!=null) jmol.evalString(printSymmetryAxes(msa, axes, false));
89+
jmol.evalString(printPointGroupAxes(msa));
90+
91+
return jmol;
92+
}
93+
94+
/**
95+
* Displays a single structure in a cartoon representation with each
96+
* symmetric subunit colored differently.
97+
*
98+
* @param msa the symmetry multiple alignment obtained from CeSymm
99+
* @throws StructureException
100+
*/
101+
public static MultipleAlignmentJmol display(MultipleAlignment msa)
102+
throws StructureException {
103+
return display(msa, null);
104+
}
105+
106+
/**
107+
* Adds a Symmetry menu to the Jmol display, so that further symmetry
108+
* analysis can be triggered.
109+
*
110+
* @param jmol parent jmol
111+
* @param axes symmetry axes
112+
*/
113+
private static void addSymmetryMenu(MultipleAlignmentJmol jmol,
114+
SymmetryAxes axes){
115+
116+
JMenuBar menubar = jmol.getFrame().getJMenuBar();
117+
118+
JMenu symm = new JMenu("Symmetry");
119+
symm.setMnemonic(KeyEvent.VK_S);
120+
121+
SymmetryListener li = new SymmetryListener(jmol, axes);
122+
123+
JMenuItem subunits = new JMenuItem("Subunit Superposition");
124+
subunits.addActionListener(li);
125+
symm.add(subunits);
126+
127+
JMenuItem multiple = new JMenuItem("Multiple Structure Alignment");
128+
multiple.addActionListener(li);
129+
symm.add(multiple);
130+
131+
JMenuItem pg = new JMenuItem("Point Group Symmetry");
132+
pg.addActionListener(li);
133+
symm.add(pg);
134+
135+
JMenuItem ax = new JMenuItem("Show Symmetry Axes");
136+
ax.addActionListener(li);
137+
symm.add(ax);
138+
139+
JMenuItem news = new JMenuItem("New Symmetry Analysis");
140+
news.addActionListener(li);
141+
symm.add(news);
142+
143+
menubar.add(symm, 3);
144+
jmol.getFrame().pack();
145+
}
146+
147+
/**
148+
* Generates a String that displays the symmetry axes of a structure.
149+
*
150+
* @param msa
151+
* @param axes
152+
* @param elementary only print elementary axes if true
153+
* @return
154+
*/
155+
public static String printSymmetryAxes(MultipleAlignment msa,
156+
SymmetryAxes axes, boolean elementary) {
157+
158+
int id = 0;
159+
String script = "";
160+
Atom[] atoms = msa.getAtomArrays().get(0);
161+
162+
List<Matrix4d> symmAxes = null;
163+
if (elementary){
164+
symmAxes = axes.getElementaryAxes();
165+
} else {
166+
symmAxes = axes.getSymmetryAxes();
167+
}
168+
169+
for (Matrix4d axis : symmAxes) {
170+
RotationAxis rot = new RotationAxis(axis);
171+
script += rot.getJmolScript(atoms, id);
172+
id++;
173+
}
174+
return script;
175+
}
176+
177+
/**
178+
* Given a symmetry alignment, it draws the point group symmetry axes
179+
* and the polyhedron box around the structure.
180+
* It uses the quaternary symmetry detection code, but tries to factor
181+
* out the alignment and detection steps.
182+
*
183+
* @param symm
184+
* @return
185+
*/
186+
public static String printPointGroupAxes(MultipleAlignment symm){
187+
188+
//Obtain the clusters of aligned Atoms and subunit variables
189+
MultipleAlignment subunits = SymmetryTools.toSubunitAlignment(symm);
190+
List<Atom[]> alignedCA = subunits.getAtomArrays();
191+
List<Integer> corePos = MultipleAlignmentTools.getCorePositions(
192+
subunits.getBlock(0));
193+
194+
List<Point3d[]> caCoords = new ArrayList<Point3d[]>();
195+
List<Integer> folds = new ArrayList<Integer>();
196+
List<Boolean> pseudo = new ArrayList<Boolean>();
197+
List<String> chainIds = new ArrayList<String>();
198+
List<Integer> models = new ArrayList<Integer>();
199+
List<Double> seqIDmin = new ArrayList<Double>();
200+
List<Double> seqIDmax = new ArrayList<Double>();
201+
List<Integer> clusterIDs = new ArrayList<Integer>();
202+
int fold = 1;
203+
Character chain = 'A';
204+
205+
for (int str=0; str<alignedCA.size(); str++){
206+
Atom[] array = alignedCA.get(str);
207+
List<Point3d> points = new ArrayList<Point3d>();
208+
List<Integer> alignedRes =
209+
subunits.getBlock(0).getAlignRes().get(str);
210+
for (int pos=0; pos<alignedRes.size(); pos++){
211+
Integer residue = alignedRes.get(pos);
212+
if (residue == null) continue;
213+
else if (!corePos.contains(pos)) continue;
214+
Atom a = array[residue];
215+
points.add(new Point3d(a.getCoords()));
216+
}
217+
caCoords.add(points.toArray(new Point3d[points.size()]));
218+
if (alignedCA.size() % fold == 0){
219+
folds.add(fold); //the folds are the common denominators
220+
}
221+
fold++;
222+
pseudo.add(false);
223+
chainIds.add(chain+"");
224+
chain++;
225+
models.add(0);
226+
seqIDmax.add(1.0);
227+
seqIDmin.add(1.0);
228+
clusterIDs.add(0);
229+
}
230+
231+
//Create directly the subunits, because we know the aligned CA
232+
Subunits globalSubunits = new Subunits(caCoords, clusterIDs,
233+
pseudo, seqIDmin, seqIDmax,
234+
folds, chainIds, models);
235+
236+
//Quaternary Symmetry Detection
237+
QuatSymmetryParameters param = new QuatSymmetryParameters();
238+
param.setRmsdThreshold(symm.size() * 1.5);
239+
240+
QuatSymmetryResults gSymmetry =
241+
QuatSymmetryDetector.calcQuatSymmetry(globalSubunits, param);
242+
243+
AxisAligner axes = AxisAligner.getInstance(gSymmetry);
244+
245+
//Draw the axes as in the quaternary symmetry
246+
JmolSymmetryScriptGenerator scriptGenerator =
247+
JmolSymmetryScriptGeneratorPointGroup.getInstance(axes, "g");
248+
249+
String script = "save selection; set defaultStructureDSSP true; "
250+
+ "set measurementUnits ANGSTROMS; select all; "
251+
+ "spacefill off; wireframe off;"
252+
+ "set antialiasDisplay true; autobond=false; ";
253+
254+
script += scriptGenerator.getOrientationWithZoom(0);
255+
script += "restore selection; ";
256+
script += scriptGenerator.drawPolyhedron();
257+
script += scriptGenerator.drawAxes();
258+
script += "draw axes* on; draw poly* on; ";
259+
260+
return script;
261+
}
262+
263+
}

0 commit comments

Comments
 (0)