Skip to content

Commit 337ca45

Browse files
committed
Implemented output of "flattened" bioassemblies (single model, chains
added)
1 parent 5c39b20 commit 337ca45

6 files changed

Lines changed: 157 additions & 32 deletions

File tree

biojava-structure-gui/src/main/java/demo/DemoOrientBioAssembly.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
import org.biojava.nbio.structure.Structure;
2424
import org.biojava.nbio.structure.StructureException;
25+
import org.biojava.nbio.structure.StructureIO;
2526
import org.biojava.nbio.structure.align.gui.jmol.StructureAlignmentJmol;
2627
import org.biojava.nbio.structure.align.util.AtomCache;
2728
import org.biojava.nbio.structure.io.FileParsingParameters;
@@ -223,10 +224,11 @@ private static Structure readStructure(String pdbId, int bioAssemblyId) {
223224
params.setParseCAOnly(true);
224225
params.setAtomCaThreshold(Integer.MAX_VALUE);
225226
cache.setFileParsingParams(params);
227+
StructureIO.setAtomCache(cache);
226228

227229
Structure structure = null;
228230
try {
229-
structure = cache.getBiologicalAssembly(pdbId, bioAssemblyId);
231+
structure = StructureIO.getBiologicalAssembly(pdbId, bioAssemblyId);
230232
} catch (IOException e) {
231233
// TODO Auto-generated catch block
232234
e.printStackTrace();

biojava-structure/src/main/java/org/biojava/nbio/structure/BioAssemblyIdentifier.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public String toString() {
6767
@Override
6868
public Structure loadStructure(AtomCache cache) throws StructureException,
6969
IOException {
70-
return cache.getBiologicalAssembly(pdbCode, biolNr);
70+
return cache.getBiologicalAssembly(pdbCode, biolNr, AtomCache.DEFAULT_BIOASSEMBLY_STYLE);
7171
}
7272

7373
@Override

biojava-structure/src/main/java/org/biojava/nbio/structure/StructureIO.java

Lines changed: 86 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -119,74 +119,148 @@ public static void setAtomCache(AtomCache c){
119119

120120
/**
121121
* Returns the first biological assembly that is available for the given PDB id.
122-
* If the assembly occurs through crystallographic symmetry, the symmetry partners
123-
* are added as new models.
122+
* <p>
123+
* The output Structure will be different depending on the multiModel parameter:
124+
* <li>
125+
* the symmetry-expanded chains are added as new models, one per transformId. All original models but
126+
* the first one are discarded.
127+
* </li>
128+
* <li>
129+
* as original with symmetry-expanded chains added with renamed chain ids and names (in the form
130+
* originalAsymId_transformId and originalAuthId_transformId)
131+
* </li>
124132
* <p>
125133
* For more documentation on quaternary structures see:
126134
* {@link http://pdb101.rcsb.org/learn/guide-to-understanding-pdb-data/biological-assemblies}
127135
*
128136
*
129137
* @param pdbId
138+
* @param multiModel if true the output Structure will be a multi-model one with one transformId per model,
139+
* if false the outputStructure will be as the original with added chains with renamed asymIds (in the form originalAsymId_transformId and originalAuthId_transformId).
130140
* @return a Structure object or null if that assembly is not available
131141
* @throws StructureException
132142
* @throws IOException
133143
*/
134-
public static Structure getBiologicalAssembly(String pdbId) throws IOException, StructureException{
144+
public static Structure getBiologicalAssembly(String pdbId, boolean multiModel) throws IOException, StructureException{
135145

136146
checkInitAtomCache();
137147

138148
pdbId = pdbId.toLowerCase();
139149

140-
Structure s = cache.getBiologicalAssembly(pdbId);
150+
Structure s = cache.getBiologicalAssembly(pdbId, multiModel);
141151

142152
return s;
143153
}
154+
155+
/**
156+
* Returns the first biological assembly that is available for the given PDB id,
157+
* using multiModel={@value AtomCache#DEFAULT_BIOASSEMBLY_STYLE}
158+
* <p>
159+
* For more documentation on quaternary structures see:
160+
* {@link http://pdb101.rcsb.org/learn/guide-to-understanding-pdb-data/biological-assemblies}
161+
*
162+
*
163+
* @param pdbId
164+
* @return a Structure object or null if that assembly is not available
165+
* @throws StructureException
166+
* @throws IOException
167+
*/
168+
public static Structure getBiologicalAssembly(String pdbId) throws IOException, StructureException{
169+
return getBiologicalAssembly(pdbId, AtomCache.DEFAULT_BIOASSEMBLY_STYLE);
170+
}
144171

145172
/**
146173
* Returns the biological assembly for the given PDB id and bioassembly identifier.
147-
* If the assembly occurs through crystallographic symmetry, the symmetry partners
148-
* are added as new models.
174+
* <p>
175+
* The output Structure will be different depending on the multiModel parameter:
176+
* <li>
177+
* the symmetry-expanded chains are added as new models, one per transformId. All original models but
178+
* the first one are discarded.
179+
* </li>
180+
* <li>
181+
* as original with symmetry-expanded chains added with renamed chain ids and names (in the form
182+
* originalAsymId_transformId and originalAuthId_transformId)
183+
* </li>
149184
* @param pdbId
150185
* @param biolAssemblyNr - the ith biological assembly that is available for a PDB ID (we start counting at 1, 0 represents the asym unit).
186+
* @param multiModel if true the output Structure will be a multi-model one with one transformId per model,
187+
* if false the outputStructure will be as the original with added chains with renamed asymIds (in the form originalAsymId_transformId and originalAuthId_transformId).
151188
* @return a Structure object or null if that assembly is not available
152189
* @throws StructureException if there is no bioassembly available for given biolAssemblyNr or some other problems encountered while loading it
153190
* @throws IOException
154191
*/
155-
public static Structure getBiologicalAssembly(String pdbId, int biolAssemblyNr) throws IOException, StructureException {
192+
public static Structure getBiologicalAssembly(String pdbId, int biolAssemblyNr, boolean multiModel) throws IOException, StructureException {
156193

157194
checkInitAtomCache();
158195

159196
pdbId = pdbId.toLowerCase();
160197

161-
Structure s = cache.getBiologicalAssembly(pdbId, biolAssemblyNr);
198+
Structure s = cache.getBiologicalAssembly(pdbId, biolAssemblyNr, multiModel);
162199

163200
return s;
164201
}
165202

203+
/**
204+
* Returns the biological assembly for the given PDB id and bioassembly identifier,
205+
* using multiModel={@value AtomCache#DEFAULT_BIOASSEMBLY_STYLE}
206+
* @param pdbId
207+
* @param biolAssemblyNr - the ith biological assembly that is available for a PDB ID (we start counting at 1, 0 represents the asym unit).
208+
* @return a Structure object or null if that assembly is not available
209+
* @throws StructureException if there is no bioassembly available for given biolAssemblyNr or some other problems encountered while loading it
210+
* @throws IOException
211+
*/
212+
public static Structure getBiologicalAssembly(String pdbId, int biolAssemblyNr) throws IOException, StructureException {
213+
return getBiologicalAssembly(pdbId, biolAssemblyNr, AtomCache.DEFAULT_BIOASSEMBLY_STYLE);
214+
}
215+
216+
166217
/**
167218
* Returns all biological assemblies for the given PDB id.
168-
* If the assembly occurs through crystallographic symmetry, the symmetry partners
169-
* are added as new models.
170219
* <p>
220+
* The output Structure will be different depending on the multiModel parameter:
221+
* <li>
222+
* the symmetry-expanded chains are added as new models, one per transformId. All original models but
223+
* the first one are discarded.
224+
* </li>
225+
* <li>
226+
* as original with symmetry-expanded chains added with renamed chain ids and names (in the form
227+
* originalAsymId_transformId and originalAuthId_transformId)
228+
* </li>
171229
* If only one biological assembly is required use {@link #getBiologicalAssembly(String)} or {@link #getBiologicalAssembly(String, int)} instead.
172230
* @param pdbId
231+
* @param multiModel if true the output Structure will be a multi-model one with one transformId per model,
232+
* if false the outputStructure will be as the original with added chains with renamed asymIds (in the form originalAsymId_transformId and originalAuthId_transformId).
173233
* @return
174234
* @throws IOException
175235
* @throws StructureException
176236
* @since 5.0
177237
*/
178-
public static List<Structure> getBiologicalAssemblies(String pdbId) throws IOException, StructureException {
238+
public static List<Structure> getBiologicalAssemblies(String pdbId, boolean multiModel) throws IOException, StructureException {
179239

180240
checkInitAtomCache();
181241

182242
pdbId = pdbId.toLowerCase();
183243

184-
List<Structure> s = cache.getBiologicalAssemblies(pdbId);
244+
List<Structure> s = cache.getBiologicalAssemblies(pdbId, multiModel);
185245

186246
return s;
187247

188248
}
189249

250+
/**
251+
* Returns all biological assemblies for the given PDB id,
252+
* using multiModel={@value AtomCache#DEFAULT_BIOASSEMBLY_STYLE}
253+
* <p>
254+
* If only one biological assembly is required use {@link #getBiologicalAssembly(String)} or {@link #getBiologicalAssembly(String, int)} instead.
255+
* @param pdbId
256+
* @return
257+
* @throws IOException
258+
* @throws StructureException
259+
* @since 5.0
260+
*/
261+
public static List<Structure> getBiologicalAssemblies(String pdbId) throws IOException, StructureException {
262+
return getBiologicalAssemblies(pdbId, AtomCache.DEFAULT_BIOASSEMBLY_STYLE);
263+
}
190264

191265

192266
private static final String FILE_SEPARATOR = System.getProperty("file.separator");

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

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@
6666
public class AtomCache {
6767

6868
private static final Logger logger = LoggerFactory.getLogger(AtomCache.class);
69+
70+
/**
71+
* The default output bioassembly style: if true the bioassemblies are multimodel,
72+
* if false the bioassemblies are flat with renamed chains for symmetry-partners.
73+
*/
74+
public static final boolean DEFAULT_BIOASSEMBLY_STYLE = true;
6975

7076
public static final String BIOL_ASSEMBLY_IDENTIFIER = "BIO:";
7177
public static final String CHAIN_NR_SYMBOL = ":";
@@ -222,6 +228,7 @@ public Atom[] getAtoms(StructureIdentifier name) throws IOException, StructureEx
222228
public Atom[] getRepresentativeAtoms(String name) throws IOException, StructureException {
223229
return getRepresentativeAtoms(new StructureName(name));
224230
}
231+
225232
public Atom[] getRepresentativeAtoms(StructureIdentifier name) throws IOException, StructureException {
226233

227234
Atom[] atoms = null;
@@ -249,13 +256,15 @@ public Atom[] getRepresentativeAtoms(StructureIdentifier name) throws IOExceptio
249256
* the PDB ID
250257
* @param bioAssemblyId
251258
* the 1-based index of the biological assembly (0 gets the asymmetric unit)
259+
* @param multiModel if true the output Structure will be a multi-model one with one transformId per model,
260+
* if false the outputStructure will be as the original with added chains with renamed asymIds (in the form originalAsymId_transformId and originalAuthId_transformId).
252261
* @return a structure object
253262
* @throws IOException
254263
* @throws StructureException if biassemblyId < 0 or other problems while loading structure
255264
* @author Peter Rose
256265
* @since 3.2
257266
*/
258-
public Structure getBiologicalAssembly(String pdbId, int bioAssemblyId)
267+
public Structure getBiologicalAssembly(String pdbId, int bioAssemblyId, boolean multiModel)
259268
throws StructureException, IOException {
260269

261270
if (bioAssemblyId < 0) {
@@ -304,7 +313,7 @@ public Structure getBiologicalAssembly(String pdbId, int bioAssemblyId)
304313
boolean useAsymIds = false;
305314
if (useMmCif) useAsymIds = true;
306315
if (useMmtf) useAsymIds = true;
307-
return builder.rebuildQuaternaryStructure(asymUnit, transformations, useAsymIds);
316+
return builder.rebuildQuaternaryStructure(asymUnit, transformations, useAsymIds, multiModel);
308317

309318
}
310319

@@ -314,14 +323,15 @@ public Structure getBiologicalAssembly(String pdbId, int bioAssemblyId)
314323
*
315324
* <p>Biological assemblies can also be accessed using
316325
* <tt>getStructure("BIO:<i>[pdbId]</i>")</tt>
317-
* @param pdbId
318-
* the PDB ID
326+
* @param pdbId the PDB id
327+
* @param multiModel if true the output Structure will be a multi-model one with one transformId per model,
328+
* if false the outputStructure will be as the original with added chains with renamed asymIds (in the form originalAsymId_transformId and originalAuthId_transformId).
319329
* @return a structure object
320330
* @throws IOException
321331
* @throws StructureException
322332
* @since 4.2
323333
*/
324-
public Structure getBiologicalAssembly(String pdbId) throws StructureException, IOException {
334+
public Structure getBiologicalAssembly(String pdbId, boolean multiModel) throws StructureException, IOException {
325335

326336
boolean prevIsParseBioAssembly = getFileParsingParams().isParseBioAssembly();
327337

@@ -362,19 +372,21 @@ public Structure getBiologicalAssembly(String pdbId) throws StructureException,
362372
boolean useAsymIds = false;
363373
if (useMmCif) useAsymIds = true;
364374
if (useMmtf) useAsymIds = true;
365-
return builder.rebuildQuaternaryStructure(asymUnit, transformations, useAsymIds);
375+
return builder.rebuildQuaternaryStructure(asymUnit, transformations, useAsymIds, multiModel);
366376

367377
}
368378

369379
/**
370380
* Returns all biological assemblies for given PDB id.
371381
* @param pdbId
382+
* @param multiModel if true the output Structure will be a multi-model one with one transformId per model,
383+
* if false the outputStructure will be as the original with added chains with renamed asymIds (in the form originalAsymId_transformId and originalAuthId_transformId).
372384
* @return
373385
* @throws StructureException
374386
* @throws IOException
375387
* @since 5.0
376388
*/
377-
public List<Structure> getBiologicalAssemblies(String pdbId) throws StructureException, IOException {
389+
public List<Structure> getBiologicalAssemblies(String pdbId, boolean multiModel) throws StructureException, IOException {
378390

379391
List<Structure> assemblies = new ArrayList<>();
380392

@@ -413,7 +425,7 @@ public List<Structure> getBiologicalAssemblies(String pdbId) throws StructureExc
413425
boolean useAsymIds = false;
414426
if (useMmCif) useAsymIds = true;
415427
if (useMmtf) useAsymIds = true;
416-
Structure s = builder.rebuildQuaternaryStructure(asymUnit, transformations, useAsymIds);
428+
Structure s = builder.rebuildQuaternaryStructure(asymUnit, transformations, useAsymIds, multiModel);
417429
assemblies.add(s);
418430
}
419431
return assemblies;

biojava-structure/src/main/java/org/biojava/nbio/structure/quaternary/BiologicalAssemblyBuilder.java

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,24 @@ public BiologicalAssemblyBuilder(){
5959
/**
6060
* Builds a Structure object containing the quaternary structure built from given asymUnit and transformations,
6161
* by adding symmetry partners as new models.
62-
* If the input Structure is multi-model, then only model 1 is retained and the quaternary structure is built
63-
* in the same way with additional models.
62+
* The output Structure will be different depending on the multiModel parameter:
63+
* <li>
64+
* the symmetry-expanded chains are added as new models, one per transformId. All original models but
65+
* the first one are discarded.
66+
* </li>
67+
* <li>
68+
* as original with symmetry-expanded chains added with renamed chain ids and names (in the form
69+
* originalAsymId_transformId and originalAuthId_transformId)
70+
* </li>
6471
* @param asymUnit
6572
* @param transformations
6673
* @param useAsymIds if true use {@link Chain#getId()} to match the ids in the BiologicalAssemblyTransformation (needed if data read from mmCIF),
6774
* if false use {@link Chain#getName()} for the chain matching (needed if data read from PDB).
75+
* @param multiModel if true the output Structure will be a multi-model one with one transformId per model,
76+
* if false the outputStructure will be as the original with added chains with renamed asymIds (in the form originalAsymId_transformId and originalAuthId_transformId).
6877
* @return
6978
*/
70-
public Structure rebuildQuaternaryStructure(Structure asymUnit, List<BiologicalAssemblyTransformation> transformations, boolean useAsymIds) {
79+
public Structure rebuildQuaternaryStructure(Structure asymUnit, List<BiologicalAssemblyTransformation> transformations, boolean useAsymIds, boolean multiModel) {
7180

7281
// ensure that new chains are build in the same order as they appear in the asymmetric unit
7382
orderTransformationsByChainId(asymUnit, transformations);
@@ -100,7 +109,7 @@ public Structure rebuildQuaternaryStructure(Structure asymUnit, List<BiologicalA
100109
for (Chain c: chainsToTransform) {
101110

102111

103-
Chain chain = (Chain)c.clone();
112+
Chain chain = (Chain)c.clone();
104113

105114
for (Group g : chain.getAtomGroups()) {
106115

@@ -113,7 +122,11 @@ public Structure rebuildQuaternaryStructure(Structure asymUnit, List<BiologicalA
113122

114123
String transformId = transformation.getId();
115124

116-
addChainAndModel(s, chain, transformId);
125+
// note that the Structure.addChain/Structure.addModel methods set the parent reference to the new Structure
126+
if (multiModel)
127+
addChainMultiModel(s, chain, transformId);
128+
else
129+
addChainFlattened(s, chain, transformId);
117130

118131
}
119132
}
@@ -156,15 +169,24 @@ private List<String> getChainIds(Structure asymUnit) {
156169
return chainIds;
157170
}
158171

159-
private void addChainAndModel(Structure s, Chain newChain, String modelId) {
172+
/**
173+
* Adds a chain to the given structure to form a biological assembly,
174+
* adding the symmetry expanded chains as new models per transformId.
175+
* @param s
176+
* @param newChain
177+
* @param transformId
178+
*/
179+
private void addChainMultiModel(Structure s, Chain newChain, String transformId) {
180+
181+
// multi-model bioassembly
160182

161183
if ( modelIndex.size() == 0)
162184
modelIndex.add("PLACEHOLDER FOR ASYM UNIT");
163185

164-
int modelCount = modelIndex.indexOf(modelId);
186+
int modelCount = modelIndex.indexOf(transformId);
165187
if ( modelCount == -1) {
166-
modelIndex.add(modelId);
167-
modelCount = modelIndex.indexOf(modelId);
188+
modelIndex.add(transformId);
189+
modelCount = modelIndex.indexOf(transformId);
168190
}
169191

170192
if (modelCount == 0) {
@@ -176,6 +198,21 @@ private void addChainAndModel(Structure s, Chain newChain, String modelId) {
176198
} else {
177199
s.addChain(newChain, modelCount-1);
178200
}
201+
202+
}
203+
204+
/**
205+
* Adds a chain to the given structure to form a biological assembly,
206+
* adding the symmetry-expanded chains as new chains with renamed
207+
* chain ids and names (in the form originalAsymId_transformId and originalAuthId_transformId).
208+
* @param s
209+
* @param newChain
210+
* @param transformId
211+
*/
212+
private void addChainFlattened(Structure s, Chain newChain, String transformId) {
213+
newChain.setId(newChain.getId()+"_"+transformId);
214+
newChain.setName(newChain.getName()+"_"+transformId);
215+
s.addChain(newChain);
179216
}
180217

181218
/**

biojava-structure/src/test/java/org/biojava/nbio/structure/symmetry/core/TestQuatSymmetryDetection.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ private String[] getSymmetry(Structure pdb, int bioUnitNumber) {
124124
BiologicalAssemblyBuilder builder = new BiologicalAssemblyBuilder();
125125

126126
// we use true in useAsymIds here because above we read mmcif files, if that changes this needs to change!
127-
Structure bioAssembly = builder.rebuildQuaternaryStructure(pdb, transformations, true);
127+
Structure bioAssembly = builder.rebuildQuaternaryStructure(pdb, transformations, true, true);
128128

129129
QuatSymmetryParameters parameters = new QuatSymmetryParameters();
130130
parameters.setOnTheFly(true);

0 commit comments

Comments
 (0)