Skip to content

Commit 8493927

Browse files
committed
Merge pull request biojava#97 from pwrose/master
Factored out code that makes polymer and intra-group bonds into its own
2 parents 7194d1d + 146d0e0 commit 8493927

5 files changed

Lines changed: 209 additions & 96 deletions

File tree

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
/*
2+
* BioJava development code
3+
*
4+
* This code may be freely distributed and modified under the
5+
* terms of the GNU Lesser General Public Licence. This should
6+
* be distributed with the code. If you do not have a copy,
7+
* see:
8+
*
9+
* http://www.gnu.org/copyleft/lesser.html
10+
*
11+
* Copyright for this code is held jointly by the individual
12+
* authors. These should be listed in @author doc comments.
13+
*
14+
* For more information on the BioJava project and its aims,
15+
* or to join the biojava-l mailing list, visit the home page
16+
* at:
17+
*
18+
* http://www.biojava.org/
19+
*
20+
* Created on Mar. 6, 2014
21+
*
22+
*/
23+
package org.biojava.bio.structure.io;
24+
25+
import java.util.ArrayList;
26+
import java.util.List;
27+
28+
import org.biojava.bio.structure.AminoAcidImpl;
29+
import org.biojava.bio.structure.Atom;
30+
import org.biojava.bio.structure.Bond;
31+
import org.biojava.bio.structure.Calc;
32+
import org.biojava.bio.structure.Chain;
33+
import org.biojava.bio.structure.Group;
34+
import org.biojava.bio.structure.NucleotideImpl;
35+
import org.biojava.bio.structure.Structure;
36+
import org.biojava.bio.structure.StructureException;
37+
import org.biojava.bio.structure.io.mmcif.ChemCompGroupFactory;
38+
import org.biojava.bio.structure.io.mmcif.model.ChemComp;
39+
import org.biojava.bio.structure.io.mmcif.model.ChemCompBond;
40+
41+
/**
42+
* Adds polymer bonds for peptides and nucleotides based on distance cutoffs and
43+
* intra-group (residue) bonds based on data from the Chemical Component Dictionary
44+
* to the Structure object.
45+
*
46+
* TODO the current implementation adds bonds to the first model only. This
47+
* should be sufficient for homogeneous models, but here are a few inhomogeneous models
48+
* in the PDB. A better handling of models should be considered in the future.
49+
*
50+
* @author Peter Rose
51+
* @author Ulysse Carion
52+
*
53+
*/
54+
public class BondMaker {
55+
/**
56+
* Maximum peptide (C - N) bond length considered for bond formation
57+
*/
58+
private static final double MAX_PEPTIDE_BOND_LENGTH = 1.8;
59+
/**
60+
* Maximum nucleotide (P - O3') bond length considered for bond formation
61+
*/
62+
private static final double MAX_NUCLEOTIDE_BOND_LENGTH = 2.1;
63+
64+
private Structure structure = null;
65+
66+
public BondMaker(Structure structure) {
67+
this.structure = structure;
68+
}
69+
70+
public void makeBonds() {
71+
formPeptideBonds();
72+
formNucleotideBonds();
73+
formIntraResidueBonds();
74+
trimBondLists();
75+
}
76+
77+
private void formPeptideBonds() {
78+
for (Chain chain : structure.getChains()) {
79+
List<Group> groups = chain.getSeqResGroups();
80+
81+
for (int i = 0; i < groups.size() - 1; i++) {
82+
if (!(groups.get(i) instanceof AminoAcidImpl)
83+
|| !(groups.get(i + 1) instanceof AminoAcidImpl))
84+
continue;
85+
86+
AminoAcidImpl tail = (AminoAcidImpl) groups.get(i);
87+
AminoAcidImpl head = (AminoAcidImpl) groups.get(i + 1);
88+
89+
// atoms with no residue number don't have atom information
90+
if (tail.getResidueNumber() == null
91+
|| head.getResidueNumber() == null) {
92+
continue;
93+
}
94+
95+
Atom carboxylC;
96+
Atom aminoN;
97+
98+
try {
99+
carboxylC = tail.getC();
100+
aminoN = head.getN();
101+
} catch (StructureException e) {
102+
// some structures may be incomplete and not store info
103+
// about all of their atoms
104+
continue;
105+
}
106+
107+
try {
108+
if (Calc.getDistance(carboxylC, aminoN) < MAX_PEPTIDE_BOND_LENGTH) {
109+
new Bond(carboxylC, aminoN, 1);
110+
}
111+
} catch (StructureException e) {
112+
// this can't happen, not sure why getDistance throws an exception
113+
}
114+
}
115+
}
116+
}
117+
118+
private void formNucleotideBonds() {
119+
for (Chain chain : structure.getChains()) {
120+
List<Group> groups = chain.getSeqResGroups();
121+
122+
for (int i = 0; i < groups.size() - 1; i++) {
123+
if (!(groups.get(i) instanceof NucleotideImpl)
124+
|| !(groups.get(i + 1) instanceof NucleotideImpl))
125+
continue;
126+
127+
NucleotideImpl tail = (NucleotideImpl) groups.get(i);
128+
NucleotideImpl head = (NucleotideImpl) groups.get(i + 1);
129+
130+
// atoms with no residue number don't have atom information
131+
if (tail.getResidueNumber() == null
132+
|| head.getResidueNumber() == null) {
133+
continue;
134+
}
135+
136+
Atom phosphorous;
137+
Atom oThreePrime;
138+
139+
phosphorous = tail.getP();
140+
oThreePrime = head.getO3Prime();
141+
142+
try {
143+
if (Calc.getDistance(phosphorous, oThreePrime) < MAX_NUCLEOTIDE_BOND_LENGTH) {
144+
new Bond(phosphorous, oThreePrime, 1);
145+
}
146+
} catch (StructureException e) {
147+
// this can't happen, not sure why getDistance throws an exception
148+
}
149+
}
150+
}
151+
}
152+
153+
private void formIntraResidueBonds() {
154+
for (Chain chain : structure.getChains()) {
155+
List<Group> groups = chain.getAtomGroups();
156+
157+
for (Group group : groups) {
158+
// atoms with no residue number don't have atom information
159+
if (group.getResidueNumber() == null) {
160+
continue;
161+
}
162+
163+
ChemComp aminoChemComp = ChemCompGroupFactory.getChemComp(group
164+
.getPDBName());
165+
166+
for (ChemCompBond chemCompBond : aminoChemComp.getBonds()) {
167+
try {
168+
Atom a = group.getAtom(chemCompBond.getAtom_id_1());
169+
Atom b = group.getAtom(chemCompBond.getAtom_id_2());
170+
int bondOrder = chemCompBond.getNumericalBondOrder();
171+
172+
new Bond(a, b, bondOrder);
173+
} catch (StructureException e) {
174+
// Some of the atoms were missing. That's fine, there's
175+
// nothing to do in this case.
176+
}
177+
}
178+
}
179+
}
180+
}
181+
182+
private void trimBondLists() {
183+
for (Chain chain : structure.getChains()) {
184+
for (Group group : chain.getAtomGroups()) {
185+
for (Atom atom : group.getAtoms()) {
186+
if (atom.getBonds().size() > 0) {
187+
((ArrayList<Bond>) atom.getBonds()).trimToSize();
188+
}
189+
}
190+
}
191+
}
192+
}
193+
}

biojava3-structure/src/main/java/org/biojava/bio/structure/io/PDBFileParser.java

Lines changed: 3 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -2815,14 +2815,13 @@ private void formBonds() {
28152815
for (SSBond disulfideBond : structure.getSSBonds()) {
28162816
formDisulfideBond(disulfideBond);
28172817
}
2818-
formPeptideBonds();
2819-
formIntraResidueBonds();
2818+
28202819
} catch (Exception e) {
28212820
e.printStackTrace();
28222821
throw new RuntimeException("Error while forming bonds for " + pdbId, e);
28232822
}
2824-
2825-
trimAtomBondLists();
2823+
BondMaker maker = new BondMaker(structure);
2824+
maker.makeBonds();
28262825
}
28272826

28282827
private void formLinkRecordBond(LinkRecord linkRecord) {
@@ -2895,92 +2894,6 @@ private Atom getAtomFromRecord(String name, String altLoc,
28952894

28962895
return group.getAtom(name);
28972896
}
2898-
2899-
/**
2900-
* The furthest one residue's C and another's N can be and still be assumed
2901-
* to be in a peptide bond.
2902-
*/
2903-
private static final double MAX_PEPTIDE_BOND_LENGTH = 1.8;
2904-
2905-
private void formPeptideBonds() throws StructureException {
2906-
for (Chain chain : structure.getChains()) {
2907-
List<Group> groups = chain.getSeqResGroups();
2908-
2909-
for (int i = 0; i < groups.size() - 1; i++) {
2910-
if (!(groups.get(i) instanceof AminoAcidImpl)
2911-
|| !(groups.get(i + 1) instanceof AminoAcidImpl))
2912-
continue;
2913-
2914-
AminoAcidImpl current = (AminoAcidImpl) groups.get(i);
2915-
AminoAcidImpl next = (AminoAcidImpl) groups.get(i + 1);
2916-
2917-
// atoms with no residue number don't have atom information
2918-
if (current.getResidueNumber() == null
2919-
|| next.getResidueNumber() == null) {
2920-
continue;
2921-
}
2922-
2923-
Atom carboxylC;
2924-
Atom aminoN;
2925-
2926-
try {
2927-
carboxylC = current.getC();
2928-
aminoN = next.getN();
2929-
} catch (StructureException e) {
2930-
// some structures may be incomplete and not store info
2931-
// about all of their atoms
2932-
continue;
2933-
}
2934-
2935-
if (Calc.getDistance(carboxylC, aminoN) < MAX_PEPTIDE_BOND_LENGTH) {
2936-
// we got ourselves a peptide bond
2937-
new Bond(carboxylC, aminoN, 1);
2938-
}
2939-
}
2940-
}
2941-
}
2942-
2943-
private void formIntraResidueBonds() {
2944-
for (Chain chain : structure.getChains()) {
2945-
List<Group> groups = chain.getAtomGroups();
2946-
2947-
for (Group group : groups) {
2948-
// atoms with no residue number don't have atom information
2949-
// also ignore water
2950-
if (group.getResidueNumber() == null || group.isWater()) {
2951-
continue;
2952-
}
2953-
2954-
ChemComp aminoChemComp = ChemCompGroupFactory.getChemComp(group
2955-
.getPDBName());
2956-
2957-
for (ChemCompBond chemCompBond : aminoChemComp.getBonds()) {
2958-
try {
2959-
Atom a = group.getAtom(chemCompBond.getAtom_id_1());
2960-
Atom b = group.getAtom(chemCompBond.getAtom_id_2());
2961-
int bondOrder = chemCompBond.getNumericalBondOrder();
2962-
2963-
new Bond(a, b, bondOrder);
2964-
} catch (StructureException e) {
2965-
// Some of the atoms were missing. That's fine, there's
2966-
// nothing to do in this case.
2967-
}
2968-
}
2969-
}
2970-
}
2971-
}
2972-
2973-
private void trimAtomBondLists() {
2974-
for (Chain chain : structure.getChains()) {
2975-
for (Group group : chain.getAtomGroups()) {
2976-
for (Atom atom : group.getAtoms()) {
2977-
if (atom.getBonds().size() > 0) {
2978-
((ArrayList<Bond>) atom.getBonds()).trimToSize();
2979-
}
2980-
}
2981-
}
2982-
}
2983-
}
29842897

29852898
private void triggerEndFileChecks(){
29862899
// finish and add ...

biojava3-structure/src/main/java/org/biojava/bio/structure/io/mmcif/ChemCompConsumer.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.biojava.bio.structure.io.mmcif.model.Refine;
3030
import org.biojava.bio.structure.io.mmcif.model.Struct;
3131
import org.biojava.bio.structure.io.mmcif.model.StructAsym;
32+
import org.biojava.bio.structure.io.mmcif.model.StructConn;
3233
import org.biojava.bio.structure.io.mmcif.model.StructKeywords;
3334
import org.biojava.bio.structure.io.mmcif.model.StructRef;
3435
import org.biojava.bio.structure.io.mmcif.model.StructRefSeq;
@@ -235,4 +236,10 @@ public void newEntitySrcSyn(EntitySrcSyn entitySrcSyn) {
235236

236237
}
237238

239+
@Override
240+
public void newStructConn(StructConn structConn) {
241+
// TODO Auto-generated method stub
242+
243+
}
244+
238245
}

biojava3-structure/src/main/java/org/biojava/bio/structure/io/mmcif/MMcifConsumer.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import org.biojava.bio.structure.io.mmcif.model.PdbxStructOperList;
4949
import org.biojava.bio.structure.io.mmcif.model.Refine;
5050
import org.biojava.bio.structure.io.mmcif.model.StructAsym;
51+
import org.biojava.bio.structure.io.mmcif.model.StructConn;
5152
import org.biojava.bio.structure.io.mmcif.model.StructKeywords;
5253
import org.biojava.bio.structure.io.mmcif.model.StructRefSeq;
5354
import org.biojava.bio.structure.io.mmcif.model.Struct;
@@ -103,6 +104,7 @@ public interface MMcifConsumer {
103104
public void newEntitySrcGen(EntitySrcGen entitySrcGen);
104105
public void newEntitySrcNat(EntitySrcNat entitySrcNat);
105106
public void newEntitySrcSyn(EntitySrcSyn entitySrcSyn);
107+
public void newStructConn(StructConn structConn);
106108

107109
/** AuditAuthor contains the info from the PDB-AUTHOR records.
108110
*

biojava3-structure/src/main/java/org/biojava/bio/structure/io/mmcif/SimpleMMcifConsumer.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1607,12 +1607,10 @@ public void newPdbxChemCompDescriptor(PdbxChemCompDescriptor desc) {
16071607

16081608
}
16091609

1610-
1611-
1612-
1613-
1614-
1615-
1610+
@Override
1611+
public void newStructConn(StructConn structConn) {
1612+
this.structConn.add(structConn);
1613+
}
16161614

16171615
}
16181616

0 commit comments

Comments
 (0)