Skip to content

Commit e4473f3

Browse files
committed
Implementing #408
Some bug fixes, some refactoring
1 parent 6a2eaa0 commit e4473f3

File tree

8 files changed

+181
-147
lines changed

8 files changed

+181
-147
lines changed

biojava-integrationtest/src/test/java/org/biojava/nbio/structure/test/StructureTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.biojava.nbio.structure.*;
2424
import org.biojava.nbio.structure.io.FileParsingParameters;
2525
import org.biojava.nbio.structure.io.PDBFileParser;
26+
import org.biojava.nbio.structure.io.SSBondImpl;
2627
import org.biojava.nbio.structure.jama.Matrix;
2728

2829
import java.io.IOException;

biojava-structure/src/main/java/org/biojava/nbio/structure/io/BondMaker.java

Lines changed: 106 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,15 @@
2727
import org.biojava.nbio.structure.io.mmcif.ChemCompProvider;
2828
import org.biojava.nbio.structure.io.mmcif.model.ChemComp;
2929
import org.biojava.nbio.structure.io.mmcif.model.ChemCompBond;
30+
import org.biojava.nbio.structure.io.mmcif.model.StructConn;
3031
import org.biojava.nbio.structure.io.util.PDBTemporaryStorageUtils.LinkRecord;
3132
import org.slf4j.Logger;
3233
import org.slf4j.LoggerFactory;
3334

3435
import java.util.ArrayList;
36+
import java.util.HashSet;
3537
import java.util.List;
38+
import java.util.Set;
3639

3740
/**
3841
* Adds polymer bonds for peptides and nucleotides based on distance cutoffs and
@@ -52,6 +55,21 @@ public class BondMaker {
5255

5356
private static final Logger logger = LoggerFactory.getLogger(BondMaker.class);
5457

58+
/**
59+
* The types of bonds that are read from struct_conn (type specified in field conn_type_id)
60+
*/
61+
public static final Set<String> BOND_TYPES_TO_PARSE;
62+
static {
63+
BOND_TYPES_TO_PARSE = new HashSet<>();
64+
BOND_TYPES_TO_PARSE.add("disulf");
65+
BOND_TYPES_TO_PARSE.add("covale");
66+
BOND_TYPES_TO_PARSE.add("covale_base");
67+
BOND_TYPES_TO_PARSE.add("covale_phosphate");
68+
BOND_TYPES_TO_PARSE.add("covale_sugar");
69+
BOND_TYPES_TO_PARSE.add("modres");
70+
}
71+
72+
5573
/**
5674
* Maximum peptide (C - N) bond length considered for bond formation
5775
*/
@@ -61,10 +79,12 @@ public class BondMaker {
6179
*/
6280
private static final double MAX_NUCLEOTIDE_BOND_LENGTH = 2.1;
6381

64-
private Structure structure = null;
82+
private Structure structure;
83+
private FileParsingParameters params;
6584

66-
public BondMaker(Structure structure) {
85+
public BondMaker(Structure structure, FileParsingParameters params) {
6786
this.structure = structure;
87+
this.params = params;
6888
}
6989

7090
/**
@@ -220,19 +240,17 @@ private void trimBondLists() {
220240
* Creates disulfide bond objects and references in the corresponding Atoms objects, given
221241
* a list of {@link SSBondImpl}s parsed from a PDB/mmCIF file.
222242
* @param disulfideBonds
223-
* @param parseCAonly
224-
* @return the list of bonds
225243
*/
226-
public List<Bond> formDisulfideBonds(List<SSBondImpl> disulfideBonds, boolean parseCAonly) {
244+
public void formDisulfideBonds(List<SSBondImpl> disulfideBonds) {
227245
List<Bond> bonds = new ArrayList<>();
228246
for (SSBondImpl disulfideBond : disulfideBonds) {
229-
Bond bond = formDisulfideBond(disulfideBond, parseCAonly);
247+
Bond bond = formDisulfideBond(disulfideBond);
230248
if (bond!=null) bonds.add(bond);
231249
}
232-
return bonds;
250+
structure.setSSBonds(bonds);
233251
}
234252

235-
private Bond formDisulfideBond(SSBondImpl disulfideBond, boolean parseCAonly) {
253+
private Bond formDisulfideBond(SSBondImpl disulfideBond) {
236254
try {
237255
Atom a = getAtomFromRecord("SG", "", "CYS",
238256
disulfideBond.getChainID1(), disulfideBond.getResnum1(),
@@ -249,11 +267,10 @@ private Bond formDisulfideBond(SSBondImpl disulfideBond, boolean parseCAonly) {
249267

250268
} catch (StructureException e) {
251269
// Note, in Calpha only mode the CYS SG's are not present.
252-
if (! parseCAonly) {
253-
logger.error("Error with the following SSBond: {}",disulfideBond.toString());
254-
throw new RuntimeException(e);
270+
if (! params.isParseCAOnly()) {
271+
logger.warn("Could not find atoms specified in SSBOND record: {}",disulfideBond.toString());
255272
} else {
256-
logger.debug("StructureException caught while forming disulfide bonds in parseCAonly mode. Error: "+e.getMessage());
273+
logger.debug("Could not find atoms specified in SSBOND record while parsing in parseCAonly mode.");
257274
}
258275

259276
return null;
@@ -263,9 +280,8 @@ private Bond formDisulfideBond(SSBondImpl disulfideBond, boolean parseCAonly) {
263280
/**
264281
* Creates bond objects from a LinkRecord as parsed from a PDB file
265282
* @param linkRecord
266-
* @param parseCAonly
267283
*/
268-
public void formLinkRecordBond(LinkRecord linkRecord, boolean parseCAonly) {
284+
public void formLinkRecordBond(LinkRecord linkRecord) {
269285
// only work with atoms that aren't alternate locations
270286
if (linkRecord.getAltLoc1().equals(" ")
271287
|| linkRecord.getAltLoc2().equals(" "))
@@ -287,19 +303,85 @@ public void formLinkRecordBond(LinkRecord linkRecord, boolean parseCAonly) {
287303
new BondImpl(a, b, 1);
288304
} catch (StructureException e) {
289305
// Note, in Calpha only mode the link atoms may not be present.
290-
if (! parseCAonly) {
291-
logger.error("Error with the following link record: {}",linkRecord.toString());
292-
//e.printStackTrace();
293-
throw new RuntimeException(e);
306+
if (! params.isParseCAOnly()) {
307+
logger.warn("Could not find atoms specified in LINK record: {}",linkRecord.toString());
294308
} else {
295-
logger.debug("StructureException caught while forming link record bonds in parseCAonly mode. Error: "+e.getMessage());
309+
logger.debug("Could not find atoms specified in LINK record while parsing in parseCAonly mode.");
296310
}
297311

298312
}
299313
}
300314

315+
public void formBondsFromStructConn(List<StructConn> structConn) {
316+
317+
final String symop = "1_555"; // For now - accept bonds within origin asymmetric unit.
318+
319+
List<Bond> ssbonds = new ArrayList<>();
320+
321+
for (StructConn conn : structConn) {
322+
323+
if (!BOND_TYPES_TO_PARSE.contains(conn.getConn_type_id())) continue;
324+
325+
String chainId1 = conn.getPtnr1_auth_asym_id();
326+
String chainId2 = conn.getPtnr2_auth_asym_id();
327+
328+
String insCode1 = "";
329+
if (!conn.getPdbx_ptnr1_PDB_ins_code().equals("?")) insCode1 = conn.getPdbx_ptnr1_PDB_ins_code();
330+
String insCode2 = "";
331+
if (!conn.getPdbx_ptnr2_PDB_ins_code().equals("?")) insCode2 = conn.getPdbx_ptnr2_PDB_ins_code();
332+
333+
String seqId1 = conn.getPtnr1_auth_seq_id();
334+
String seqId2 = conn.getPtnr2_auth_seq_id();
335+
String resName1 = conn.getPtnr1_label_comp_id();
336+
String resName2 = conn.getPtnr2_label_comp_id();
337+
String atomName1 = conn.getPtnr1_label_atom_id();
338+
String atomName2 = conn.getPtnr2_label_atom_id();
339+
String altLoc1 = "";
340+
if (!conn.getPdbx_ptnr1_label_alt_id().equals("?")) altLoc1 = conn.getPdbx_ptnr1_label_alt_id();
341+
String altLoc2 = "";
342+
if (!conn.getPdbx_ptnr2_label_alt_id().equals("?")) altLoc2 = conn.getPdbx_ptnr2_label_alt_id();
343+
344+
Atom a1 = null;
345+
Atom a2 = null;
346+
347+
try {
348+
a1 = getAtomFromRecord(atomName1, altLoc1, resName1, chainId1, seqId1, insCode1);
349+
350+
} catch (StructureException e) {
351+
logger.warn("Could not find atom specified in struct_conn record: {}{}({}) in chain {}, atom {}", seqId1, insCode1, resName1, chainId1, atomName1);
352+
continue;
353+
}
354+
try {
355+
a2 = getAtomFromRecord(atomName2, altLoc2, resName2, chainId2, seqId2, insCode2);
356+
} catch (StructureException e) {
357+
logger.warn("Could not find atom specified in struct_conn record: {}{}({}) in chain {}, atom {}", seqId2, insCode2, resName2, chainId2, atomName2);
358+
continue;
359+
}
360+
361+
362+
// TODO: when issue 220 is implemented, add robust symmetry handling to allow bonds between symmetry-related molecules.
363+
if (!conn.getPtnr1_symmetry().equals(symop) || !conn.getPtnr2_symmetry().equals(symop) ) {
364+
logger.info("Skipping bond between atoms {}({}) and {}({}) belonging to different symmetry partners, because it is not supported yet",
365+
a1.getPDBserial(), a1.getName(), a2.getPDBserial(), a2.getName());
366+
continue;
367+
}
368+
369+
// assuming order 1 for all bonds, no information is provided by struct_conn
370+
Bond bond = new BondImpl(a1, a2, 1);
371+
372+
if (conn.getConn_type_id().equals("disulf")) {
373+
ssbonds.add(bond);
374+
}
375+
376+
}
377+
378+
// only for ss bonds we add a specific map in structure, all the rests are linked only from Atom.getBonds
379+
structure.setSSBonds(ssbonds);
380+
}
381+
301382
private Atom getAtomFromRecord(String name, String altLoc, String resName, String chainID, String resSeq, String iCode)
302383
throws StructureException {
384+
303385
if (iCode==null || iCode.isEmpty()) {
304386
iCode = " "; // an insertion code of ' ' is ignored
305387
}
@@ -308,11 +390,14 @@ private Atom getAtomFromRecord(String name, String altLoc, String resName, Strin
308390
ResidueNumber resNum = new ResidueNumber(chainID, Integer.parseInt(resSeq), iCode.charAt(0));
309391
Group group = chain.getGroupByPDB(resNum);
310392

393+
Group g = group;
311394
// there is an alternate location
312395
if (!altLoc.isEmpty()) {
313-
group = group.getAltLocGroup(altLoc.charAt(0));
396+
g = group.getAltLocGroup(altLoc.charAt(0));
397+
if (g==null)
398+
throw new StructureException("Could not find altLoc code "+altLoc+" in group "+resSeq+iCode+" of chain "+ chainID);
314399
}
315400

316-
return group.getAtom(name);
401+
return g.getAtom(name);
317402
}
318403
}

biojava-structure/src/main/java/org/biojava/nbio/structure/io/FileConvert.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939
import org.biojava.nbio.structure.Group;
4040
import org.biojava.nbio.structure.GroupType;
4141
import org.biojava.nbio.structure.PDBHeader;
42-
import org.biojava.nbio.structure.SSBondImpl;
4342
import org.biojava.nbio.structure.Site;
4443
import org.biojava.nbio.structure.Structure;
4544
import org.biojava.nbio.structure.io.mmcif.MMCIFFileTools;

biojava-structure/src/main/java/org/biojava/nbio/structure/io/PDBFileParser.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@
6666
import org.biojava.nbio.structure.PDBCrystallographicInfo;
6767
import org.biojava.nbio.structure.PDBHeader;
6868
import org.biojava.nbio.structure.ResidueNumber;
69-
import org.biojava.nbio.structure.SSBondImpl;
7069
import org.biojava.nbio.structure.Site;
7170
import org.biojava.nbio.structure.Structure;
7271
import org.biojava.nbio.structure.StructureException;
@@ -2815,14 +2814,14 @@ private void makeCompounds(List<String> compoundList,
28152814
*/
28162815
private void formBonds() {
28172816

2818-
BondMaker maker = new BondMaker(structure);
2817+
BondMaker maker = new BondMaker(structure, params);
28192818

28202819
// TODO do we want link records at all? aren't they overlapping with other bonds that we infer (peptide/nucleotide bonds) or get from chemical components (intra-molecule bonds) - JD 2016-03-03
28212820
for (LinkRecord linkRecord : linkRecords) {
2822-
maker.formLinkRecordBond(linkRecord, parseCAonly);
2821+
maker.formLinkRecordBond(linkRecord);
28232822
}
28242823

2825-
maker.formDisulfideBonds(ssbonds, parseCAonly);
2824+
maker.formDisulfideBonds(ssbonds);
28262825

28272826
maker.makeBonds();
28282827
}

biojava-structure/src/main/java/org/biojava/nbio/structure/SSBondImpl.java renamed to biojava-structure/src/main/java/org/biojava/nbio/structure/io/SSBondImpl.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,15 @@
2121
*
2222
*/
2323

24-
package org.biojava.nbio.structure;
24+
package org.biojava.nbio.structure.io;
2525

2626
import java.io.Serializable;
2727
import java.util.ArrayList;
2828
import java.util.List;
2929

30+
import org.biojava.nbio.structure.Bond;
31+
import org.biojava.nbio.structure.PDBRecord;
32+
3033
/**
3134
* A simple bean to store disulfide bridge information, the SSBOND records in the PDB files.
3235
*

0 commit comments

Comments
 (0)