Skip to content

Commit 3509775

Browse files
authored
Merge pull request biojava#502 from andreasprlic/master
Adds a new definitions file for the correct detection of metal bonds.
2 parents 1d874f1 + 58c6743 commit 3509775

11 files changed

Lines changed: 518 additions & 263 deletions

File tree

‎biojava-modfinder/src/main/java/org/biojava/nbio/protmod/structure/StructureUtil.java‎

Lines changed: 65 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,13 @@
2525
package org.biojava.nbio.protmod.structure;
2626

2727
import org.biojava.nbio.structure.*;
28+
import org.biojava.nbio.structure.io.mmcif.MetalBondParser;
29+
import org.biojava.nbio.structure.io.mmcif.chem.MetalBondDistance;
2830

2931
import java.util.ArrayList;
3032
import java.util.Collections;
3133
import java.util.List;
34+
import java.util.Map;
3235

3336
public final class StructureUtil {
3437
private StructureUtil() {
@@ -242,18 +245,74 @@ public static Atom[] findLinkage(final Group group1, final Group group2,
242245

243246
return ret;
244247
}
245-
248+
249+
// is it a metal ?
250+
251+
if ( a1.getElement().isMetal() || a2.getElement().isMetal()){
252+
253+
MetalBondDistance defined = getMetalDistanceCutoff(a1.getElement().name(),a2.getElement().name());
254+
255+
if ( defined != null) {
256+
257+
if (hasMetalBond(a1, a2, defined))
258+
return ret;
259+
else
260+
return null;
261+
}
262+
263+
}
264+
265+
// not a metal
266+
267+
double distance = Calc.getDistance(a1, a2);
268+
269+
float radiusOfAtom1 = ret[0].getElement().getCovalentRadius();
270+
float radiusOfAtom2 = ret[1].getElement().getCovalentRadius();
271+
272+
if (Math.abs(distance - radiusOfAtom1 - radiusOfAtom2)
273+
> bondLengthTolerance) {
274+
return null;
275+
}
276+
277+
278+
return ret;
279+
}
280+
281+
private static boolean hasMetalBond(Atom a1, Atom a2, MetalBondDistance definition) {
282+
246283
double distance = Calc.getDistance(a1,a2);
247284

248-
float radiusOfAtom1 = ret[0].getElement().getCovalentRadius();
249-
float radiusOfAtom2 = ret[1].getElement().getCovalentRadius();
285+
Float min = definition.getLowerLimit();
286+
Float max = definition.getUpperLimit();
287+
288+
return ( min < distance && max > distance);
289+
290+
}
291+
292+
private static MetalBondDistance getMetalDistanceCutoff(String name1, String name2) {
293+
Map<String,List<MetalBondDistance>> defs= MetalBondParser.getMetalBondDefinitions();
250294

251-
if (Math.abs(distance-radiusOfAtom1 -radiusOfAtom2)
252-
> bondLengthTolerance) {
295+
List<MetalBondDistance> distances = defs.get(name1);
296+
297+
if ( distances == null){
298+
299+
distances = defs.get(name2);
300+
String tmp = name1;
301+
name2 = name1;
302+
name1 = tmp;
303+
}
304+
if ( distances == null){
253305
return null;
254306
}
255307

256-
return ret;
308+
for ( MetalBondDistance d : distances){
309+
if ( name1.equalsIgnoreCase(d.getAtomType1()) && name2.equalsIgnoreCase(d.getAtomType2()) )
310+
return d;
311+
}
312+
313+
// no matching atom definitions found
314+
return null;
315+
257316
}
258317

259318
/**

‎biojava-modfinder/src/main/resources/org/biojava/nbio/protmod/ptm_list.xml‎

Lines changed: 26 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<ProteinModifications>
33
<Revisions>
4-
<Revision>
5-
<Date>2016-05-10</Date>
6-
<Change>Added definition for PLP</Change>
7-
<Date>2011-08-12</Date>
8-
<Change>Added glycosylation entries 386-429</Change>
4+
<Revision>
5+
<Date>2016-06-10</Date>
6+
<Change>Updated legacy chemical component and atom names to current naming conventions. Removed two obsolete entires (CLE and CGL)</Change>
7+
</Revision>
8+
<Revision>
9+
<Date>2016-05-10</Date>
10+
<Change>Added definition for PLP</Change>
11+
<Date>2011-08-12</Date>
12+
<Change>Added glycosylation entries 386-429</Change>
913
</Revision>
1014
<Revision>
1115
<Date>2011-07-26</Date>
@@ -730,7 +734,7 @@
730734
<SystematicName>(R)-2-amino-3-selanylpropanoic acid</SystematicName>
731735
<CrossReference>
732736
<Source>PDBCC</Source>
733-
<Id>CSE</Id>
737+
<Id>SEC</Id>
734738
<Name>selenocysteine</Name>
735739
</CrossReference>
736740
<CrossReference>
@@ -745,7 +749,7 @@
745749
</CrossReference>
746750
<Condition>
747751
<Component component="1">
748-
<Id source="PDBCC">CSE</Id>
752+
<Id source="PDBCC">SEC</Id>
749753
</Component>
750754
</Condition>
751755
<Occurrence>natural</Occurrence>
@@ -1353,35 +1357,6 @@
13531357
<Category>modified residue</Category>
13541358
<Keyword>amidated carboxyl end</Keyword>
13551359
</Entry>
1356-
<Entry>
1357-
<Id>0045</Id>
1358-
<Description>A protein modification that effectively converts an L-leucine residue to L-leucine amide.</Description>
1359-
<SystematicName>(S)-2-amino-4-methylpentanamide</SystematicName>
1360-
<CrossReference>
1361-
<Source>PDBCC</Source>
1362-
<Id>CLE</Id>
1363-
<Name>leucine amide</Name>
1364-
</CrossReference>
1365-
<CrossReference>
1366-
<Source>RESID</Source>
1367-
<Id>AA0091</Id>
1368-
<Name>L-leucine amide</Name>
1369-
</CrossReference>
1370-
<CrossReference>
1371-
<Source>PSI-MOD</Source>
1372-
<Id>MOD:00100</Id>
1373-
<Name>L-leucine amide</Name>
1374-
</CrossReference>
1375-
<Condition>
1376-
<Component component="1">
1377-
<Id source="PDBCC">CLE</Id>
1378-
<Terminal>C</Terminal>
1379-
</Component>
1380-
</Condition>
1381-
<Occurrence>natural</Occurrence>
1382-
<Category>modified residue</Category>
1383-
<Keyword>amidated carboxyl end</Keyword>
1384-
</Entry>
13851360
<Entry>
13861361
<Id>0046</Id>
13871362
<Description>A protein modification that effectively converts an L-phenylalanine residue to L-phenylalanine amide.</Description>
@@ -3755,7 +3730,7 @@
37553730
<SystematicName>(R)-2-amino-2-carboxyethanesulfinic acid</SystematicName>
37563731
<CrossReference>
37573732
<Source>PDBCC</Source>
3758-
<Id>CSW</Id>
3733+
<Id>CSD</Id>
37593734
<Name>cysteine-S-dioxide</Name>
37603735
</CrossReference>
37613736
<CrossReference>
@@ -3770,7 +3745,7 @@
37703745
</CrossReference>
37713746
<Condition>
37723747
<Component component="1">
3773-
<Id source="PDBCC">CSW</Id>
3748+
<Id source="PDBCC">CSD</Id>
37743749
</Component>
37753750
</Condition>
37763751
<Occurrence>natural</Occurrence>
@@ -4575,30 +4550,37 @@
45754550
</Component>
45764551
<Bond>
45774552
<Atom component="1">SG</Atom>
4553+
<!--<Atom component="8">*</Atom>-->
45784554
<Atom component="8">FE1,FE2,FE3,FE4,FE5,FE6,FE7,FE8</Atom>
45794555
</Bond>
45804556
<Bond>
45814557
<Atom component="2">SG</Atom>
4558+
<!--<Atom component="8">*</Atom>-->
45824559
<Atom component="8">FE1,FE2,FE3,FE4,FE5,FE6,FE7,FE8</Atom>
45834560
</Bond>
45844561
<Bond>
45854562
<Atom component="3">SG</Atom>
4563+
<!--<Atom component="8">*</Atom>-->
45864564
<Atom component="8">FE1,FE2,FE3,FE4,FE5,FE6,FE7,FE8</Atom>
45874565
</Bond>
45884566
<Bond>
45894567
<Atom component="4">SG</Atom>
4568+
<!--<Atom component="8">*</Atom>-->
45904569
<Atom component="8">FE1,FE2,FE3,FE4,FE5,FE6,FE7,FE8</Atom>
45914570
</Bond>
45924571
<Bond>
45934572
<Atom component="5">SG</Atom>
4573+
<!--<Atom component="8">*</Atom>-->
45944574
<Atom component="8">FE1,FE2,FE3,FE4,FE5,FE6,FE7,FE8</Atom>
45954575
</Bond>
45964576
<Bond>
45974577
<Atom component="6">SG</Atom>
4578+
<!--<Atom component="8">*</Atom>-->
45984579
<Atom component="8">FE1,FE2,FE3,FE4,FE5,FE6,FE7,FE8</Atom>
45994580
</Bond>
46004581
<Bond>
46014582
<Atom component="7">OG</Atom>
4583+
<!--<Atom component="8">*</Atom>-->
46024584
<Atom component="8">FE1,FE2,FE3,FE4,FE5,FE6,FE7,FE8</Atom>
46034585
</Bond>
46044586
</Condition>
@@ -6788,8 +6770,8 @@
67886770
<Id source="PDBCC">SEC</Id>
67896771
</Component>
67906772
<Bond>
6791-
<Atom component="1">SEG</Atom>
6792-
<Atom component="2">SEG</Atom>
6773+
<Atom component="1">SE</Atom>
6774+
<Atom component="2">SE</Atom>
67936775
</Bond>
67946776
</Condition>
67956777
<Occurrence>hypothetical</Occurrence>
@@ -6997,7 +6979,7 @@
69976979
</Component>
69986980
<Bond>
69996981
<Atom component="1">SG</Atom>
7000-
<Atom component="2">SEG</Atom>
6982+
<Atom component="2">SE</Atom>
70016983
</Bond>
70026984
</Condition>
70036985
<Occurrence>natural</Occurrence>
@@ -7060,7 +7042,7 @@
70607042
<Id source="PDBCC">TY2</Id>
70617043
</Component>
70627044
<Bond>
7063-
<Atom component="1">CE2,CE1</Atom>
7045+
<Atom component="1">CE2</Atom>
70647046
<Atom component="2">NE2</Atom>
70657047
</Bond>
70667048
</Condition>
@@ -9629,39 +9611,6 @@
96299611
<Occurrence>natural</Occurrence>
96309612
<Category>attachment</Category>
96319613
<Keyword>phosphoprotein</Keyword>
9632-
</Entry>
9633-
<Entry>
9634-
<Id>0290</Id>
9635-
<Description>A protein modification that effectively converts an L-cysteine residue to S-glutathionyl-L-cysteine.</Description>
9636-
<SystematicName>(2S)-2-amino-3-((2S)-2-((4R)-4-amino-4-carboxyl-1-oxobutyl)amino-3-(carboxylmethyl)amino-3-oxo-propyl)dithio-propanoic acid</SystematicName>
9637-
<CrossReference>
9638-
<Source>PDBCC</Source>
9639-
<Id>CGL</Id>
9640-
<Name></Name>
9641-
</CrossReference>
9642-
<CrossReference>
9643-
<Source>RESID</Source>
9644-
<Id>AA0229</Id>
9645-
<Name>L-cysteine glutathione disulfide</Name>
9646-
</CrossReference>
9647-
<CrossReference>
9648-
<Source>PSI-MOD</Source>
9649-
<Id>MOD:00234</Id>
9650-
<Name>L-cysteine glutathione disulfide</Name>
9651-
</CrossReference>
9652-
<CrossReference>
9653-
<Source>PDBCC</Source>
9654-
<Id>CGL</Id>
9655-
<Name>cystine-glutathione</Name>
9656-
</CrossReference>
9657-
<Condition>
9658-
<Component component="1">
9659-
<Id source="PDBCC">CGL</Id>
9660-
</Component>
9661-
</Condition>
9662-
<Occurrence>natural</Occurrence>
9663-
<Category>modified residue</Category>
9664-
<Keyword>disulfide bond</Keyword>
96659614
</Entry>
96669615
<Entry>
96679616
<Id>0291</Id>
@@ -9983,7 +9932,7 @@
99839932
<SystematicName>(2R)-2-amino-6-[(2R,3R)-3-methyl-3,4-dihydro-2H-pyrrol-2-ylcarbonyl]aminohexanoic acid</SystematicName>
99849933
<CrossReference>
99859934
<Source>PDBCC</Source>
9986-
<Id>PYH</Id>
9935+
<Id>PYL</Id>
99879936
<Name>N6-{[(2R,3R)-3-methyl-3,4-dihydro-2H-pyrrol-2-yl]carbonyl}-L-lysine</Name>
99889937
</CrossReference>
99899938
<CrossReference>
@@ -9998,7 +9947,7 @@
99989947
</CrossReference>
99999948
<Condition>
100009949
<Component component="1">
10001-
<Id source="PDBCC">PYH</Id>
9950+
<Id source="PDBCC">PYL</Id>
100029951
</Component>
100039952
</Condition>
100049953
<Occurrence>natural</Occurrence>

‎biojava-modfinder/src/test/java/org/biojava/nbio/protmod/structure/ProteinModificationParserTest.java‎

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,7 @@
2727
import junit.framework.TestCase;
2828
import org.biojava.nbio.protmod.ProteinModification;
2929
import org.biojava.nbio.protmod.ProteinModificationRegistry;
30-
import org.biojava.nbio.structure.ResidueNumber;
31-
import org.biojava.nbio.structure.Structure;
32-
import org.biojava.nbio.structure.StructureException;
30+
import org.biojava.nbio.structure.*;
3331
import org.slf4j.Logger;
3432
import org.slf4j.LoggerFactory;
3533

@@ -90,13 +88,27 @@ public static String[][] setUpShortTest() {
9088
{"3H8L", "AA0513"}, // CYS-S3H-CYS
9189
{"1CAD", null}, // FE and 4 Cys, cross-link4
9290

93-
// Terbium
91+
// Terbium cases
9492
{"1NCZ", null},
95-
//{"3LTQ",null}, has metalc, we ignore those for now
96-
// {"4ESQ",null},
97-
// {"1TJB",null},
98-
// {"2V15",null},
99-
// {"2K61",null},
93+
{"3LTQ",null}, // has metalc,
94+
{"4ESQ",null},
95+
{"1TJB",null},
96+
{"2V15",null},
97+
{"2K61",null},
98+
99+
// iron bond to CYS
100+
//{"1G20","AA0300"},
101+
102+
{"3CM6",null},
103+
{"1W6Z",null},
104+
//{"1Z2M",null}, distances are too big for the new cutoffs
105+
{"2O6N",null},
106+
{"1GA7",null},
107+
{"1ACD","AA0262"}, // test for CSD
108+
{"1AA6","AA0022"} , // test for SEC
109+
110+
{"1WCT","AA0179"},
111+
{"2VH3","AA0459"},
100112

101113
};
102114
return strucs;
@@ -330,16 +342,35 @@ private void parserTest(String pdbId, String residId) throws IOException, Struct
330342

331343
private void parserTest(String pdbId, Set<ProteinModification> mods) throws IOException, StructureException {
332344
Structure struc = TmpAtomCache.cache.getStructure(pdbId);
345+
/*
346+
//needed for testing 1G20
347+
if ( pdbId.equalsIgnoreCase("1G20")) {
348+
Structure n = new StructureImpl();
349+
350+
n.addChain(struc.getPolyChainByPDB("A"));
351+
n.addChain(struc.getPolyChainByPDB("B"));
352+
for (Chain c : struc.getNonPolyChainsByPDB("A"))
353+
n.addChain(c);
354+
355+
for (Chain c : struc.getNonPolyChainsByPDB("B"))
356+
n.addChain(c);
357+
358+
359+
struc = n;
360+
}
361+
*/
333362

334363
ProteinModificationIdentifier parser = new ProteinModificationIdentifier();
335364
boolean recordUnidentifiable = false;
336365
parser.setRecordUnidentifiableCompounds(recordUnidentifiable);
337-
// parser.setbondLengthTolerance(2);
366+
//parser.setbondLengthTolerance(2);
338367

339368
assertFalse(mods.isEmpty());
340369

341370
parser.identify(struc, mods);
342371

372+
//System.out.println(parser.getUnidentifiableModifiedResidues());
373+
343374
if ( parser.getIdentifiedModifiedCompound().isEmpty() ){
344375
String msg = "Did not identify any modified compounds for " + pdbId;
345376
logger.warn(msg);

0 commit comments

Comments
 (0)