Skip to content

Commit f333809

Browse files
committed
Rewrite of the pdb parser so that data fits into the new data model
i.e. chains are split into polymer, nonpolymer and waters, assigning entities and new asym ids following same rules as mmcif files. Some issues still need to be solved
1 parent 403cd68 commit f333809

4 files changed

Lines changed: 405 additions & 262 deletions

File tree

‎biojava-integrationtest/src/test/java/org/biojava/nbio/structure/test/io/TestLongPdbVsMmCifParsing.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ private void testChains(Structure sPdb, Structure sCif) throws StructureExceptio
403403

404404
assertEquals(sPdb.getNonPolyChains().size(), sCif.getNonPolyChains().size());
405405

406-
//assertEquals(sPdb.getWaterChains().size(), sCif.getWaterChains().size());
406+
assertEquals(sPdb.getWaterChains().size(), sCif.getWaterChains().size());
407407

408408
assertEquals(sPdb.getChains().size(),sCif.getChains().size());
409409

‎biojava-structure/src/main/java/org/biojava/nbio/structure/Model.java‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,4 +101,9 @@ public void addChain(Chain c) {
101101
public int size() {
102102
return polyChains.size() + nonPolyChains.size() + waterChains.size();
103103
}
104+
105+
@Override
106+
public String toString() {
107+
return "["+polyChains.size()+" poly chains, "+nonPolyChains.size()+" non-poly chains, "+waterChains.size()+" water chains]";
108+
}
104109
}

‎biojava-structure/src/main/java/org/biojava/nbio/structure/io/EntityFinder.java‎

Lines changed: 113 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -79,18 +79,51 @@ public class EntityFinder {
7979
*/
8080
public static final double GAP_COVERAGE_THRESHOLD = 0.3;
8181

82-
//private Structure s;
83-
private List<List<Chain>> allModels;
82+
83+
private List<List<Chain>> polyModels;
84+
private List<List<Chain>> nonPolyModels;
85+
private List<List<Chain>> waterModels;
8486

8587
public EntityFinder(Structure s) {
86-
allModels = new ArrayList<List<Chain>>();
88+
List<List<Chain>> allModels = new ArrayList<List<Chain>>();
8789
for (int i=0;i<s.nrModels();i++) {
88-
this.allModels.add(s.getModel(i));
90+
allModels.add(s.getModel(i));
8991
}
92+
initModels(allModels);
9093
}
9194

9295
public EntityFinder(List<List<Chain>> allModels) {
93-
this.allModels = allModels;
96+
initModels(allModels);
97+
}
98+
99+
private void initModels(List<List<Chain>> allModels) {
100+
polyModels = new ArrayList<>();
101+
nonPolyModels = new ArrayList<>();
102+
waterModels = new ArrayList<>();
103+
104+
for (List<Chain> model:allModels) {
105+
106+
List<Chain> polyChains = new ArrayList<>();
107+
List<Chain> nonPolyChains = new ArrayList<>();
108+
List<Chain> waterChains = new ArrayList<>();
109+
110+
polyModels.add(polyChains);
111+
nonPolyModels.add(nonPolyChains);
112+
waterModels.add(waterChains);
113+
114+
for (Chain c:model) {
115+
116+
if (StructureTools.isChainWaterOnly(c)) {
117+
waterChains.add(c);
118+
119+
} else if (StructureTools.isChainPureNonPolymer(c)) {
120+
nonPolyChains.add(c);
121+
122+
} else {
123+
polyChains.add(c);
124+
}
125+
}
126+
}
94127
}
95128

96129
/**
@@ -102,18 +135,18 @@ public List<EntityInfo> findEntities() {
102135

103136
TreeMap<String,EntityInfo> chainIds2entities = findCompoundsFromAlignment();
104137

105-
List<EntityInfo> compounds = findUniqueCompounds(chainIds2entities);
138+
List<EntityInfo> entities = findUniqueEntities(chainIds2entities);
106139

107-
createPurelyNonPolyCompounds(compounds);
140+
createPurelyNonPolyEntities(polyModels, nonPolyModels, waterModels, entities);
108141

109-
return compounds;
142+
return entities;
110143
}
111144

112145
/**
113146
* Utility method to obtain a list of unique entities from the chainIds2entities map
114147
* @return
115148
*/
116-
private static List<EntityInfo> findUniqueCompounds(TreeMap<String,EntityInfo> chainIds2entities) {
149+
private static List<EntityInfo> findUniqueEntities(TreeMap<String,EntityInfo> chainIds2entities) {
117150

118151
List<EntityInfo> list = new ArrayList<EntityInfo>();
119152

@@ -130,45 +163,71 @@ private static List<EntityInfo> findUniqueCompounds(TreeMap<String,EntityInfo> c
130163
return list;
131164
}
132165

133-
private void createPurelyNonPolyCompounds(List<EntityInfo> compounds) {
134-
135-
List<Chain> pureNonPolymerChains = new ArrayList<Chain>();
136-
for (int i=0;i<allModels.get(0).size();i++) {
137-
if (StructureTools.isChainPureNonPolymer(allModels.get(0).get(i))) {
138-
pureNonPolymerChains.add(allModels.get(0).get(i));
139-
}
166+
/**
167+
* Given all chains of all models find entities for the nonpolymers and water chains within them,
168+
* assigning entity ids, types and descriptions to them. The result is written back to the passed entities List.
169+
* @param allModels
170+
* @param entities
171+
*/
172+
public static void createPurelyNonPolyEntities(List<List<Chain>> polyModels, List<List<Chain>> nonPolyModels, List<List<Chain>> waterModels, List<EntityInfo> entities) {
173+
174+
// let's find first the max entity id to assign entity ids to the newly found entities
175+
int maxMolId = 0;
176+
if (!entities.isEmpty()) {
177+
maxMolId = Collections.max(entities, new Comparator<EntityInfo>() {
178+
@Override
179+
public int compare(EntityInfo o1, EntityInfo o2) {
180+
return new Integer(o1.getMolId()).compareTo(o2.getMolId());
181+
}
182+
}).getMolId();
140183
}
141-
142-
if (!pureNonPolymerChains.isEmpty()) {
143-
144-
int maxMolId = 0; // if we have no compounds at all we just use 0, so that first assignment is 1
145-
if (!compounds.isEmpty()) {
146-
Collections.max(compounds, new Comparator<EntityInfo>() {
147-
@Override
148-
public int compare(EntityInfo o1, EntityInfo o2) {
149-
return new Integer(o1.getMolId()).compareTo(o2.getMolId());
150-
}
151-
}).getMolId();
152-
}
153-
154-
int molId = maxMolId + 1;
155-
// for the purely non-polymeric chains we assign additional compounds
156-
for (Chain c: pureNonPolymerChains) {
157-
EntityInfo comp = new EntityInfo();
158-
comp.addChain(c);
159-
comp.setMolId(molId);
160-
if (StructureTools.isChainWaterOnly(c)) {
161-
comp.setType(EntityType.WATER);
162-
} else {
163-
comp.setType(EntityType.NONPOLYMER);
184+
// we go one over the max
185+
maxMolId++;
186+
187+
// TODO do this correctly for all models, not just first one!
188+
189+
if (!nonPolyModels.get(0).isEmpty()) {
190+
List<EntityInfo> nonPolyEntities = new ArrayList<>();
191+
for (Chain c: nonPolyModels.get(0)) {
192+
// we assume there's only 1 group per non-poly chain
193+
String molecPdbName = c.getAtomGroup(0).getPDBName();
194+
195+
EntityInfo nonPolyEntity = findNonPolyEntityWithDescription(molecPdbName, nonPolyEntities);
196+
if (nonPolyEntity == null) {
197+
nonPolyEntity = new EntityInfo();
198+
nonPolyEntity.setDescription(molecPdbName);
199+
nonPolyEntity.setType(EntityType.NONPOLYMER);
200+
nonPolyEntity.setMolId(maxMolId++);
201+
nonPolyEntities.add(nonPolyEntity);
202+
164203
}
165-
logger.warn("Chain {} is purely non-polymeric, will assign a new Compound (entity) to it (entity id {})", c.getId(), molId);
166-
molId++;
167-
168-
compounds.add(comp);
204+
nonPolyEntity.addChain(c);
205+
c.setEntityInfo(nonPolyEntity);
169206
}
170-
207+
entities.addAll(nonPolyEntities);
208+
}
209+
210+
if (!waterModels.get(0).isEmpty()) {
211+
EntityInfo waterEntity = new EntityInfo();
212+
waterEntity.setType(EntityType.WATER);
213+
waterEntity.setDescription("water");
214+
waterEntity.setMolId(maxMolId);
215+
216+
for (Chain waterChain:waterModels.get(0)) {
217+
waterEntity.addChain(waterChain);
218+
waterChain.setEntityInfo(waterEntity);
219+
}
220+
entities.add(waterEntity);
221+
}
222+
223+
224+
}
225+
226+
private static EntityInfo findNonPolyEntityWithDescription(String description, List<EntityInfo> nonPolyEntities) {
227+
for (EntityInfo e:nonPolyEntities) {
228+
if (e.getDescription().equals(description)) return e;
171229
}
230+
return null;
172231
}
173232

174233

@@ -221,13 +280,8 @@ private TreeMap<String,EntityInfo> findCompoundsFromAlignment() {
221280
// first we determine which chains to consider: anything not looking
222281
// polymeric (protein or nucleotide chain) should be discarded
223282
Set<Integer> polyChainIndices = new TreeSet<Integer>();
224-
List<Chain> pureNonPolymerChains = new ArrayList<Chain>();
225-
for (int i=0;i<allModels.get(0).size();i++) {
226-
if (StructureTools.isChainPureNonPolymer(allModels.get(0).get(i))) {
227-
pureNonPolymerChains.add(allModels.get(0).get(i));
228-
} else {
229-
polyChainIndices.add(i);
230-
}
283+
for (int i=0;i<polyModels.get(0).size();i++) {
284+
polyChainIndices.add(i);
231285
}
232286

233287

@@ -241,8 +295,8 @@ private TreeMap<String,EntityInfo> findCompoundsFromAlignment() {
241295

242296
if (j<=i) continue;
243297

244-
Chain c1 = allModels.get(0).get(i);
245-
Chain c2 = allModels.get(0).get(j);
298+
Chain c1 = polyModels.get(0).get(i);
299+
Chain c2 = polyModels.get(0).get(j);
246300

247301
Map<Integer,Integer> positionIndex1 = new HashMap<Integer, Integer>();
248302
Map<Integer,Integer> positionIndex2 = new HashMap<Integer, Integer>();
@@ -308,6 +362,8 @@ private TreeMap<String,EntityInfo> findCompoundsFromAlignment() {
308362
ent.addChain(c2);
309363
ent.setMolId(molId++);
310364
ent.setType(EntityType.POLYMER);
365+
c1.setEntityInfo(ent);
366+
c2.setEntityInfo(ent);
311367
chainIds2compounds.put(c1.getId(), ent);
312368
chainIds2compounds.put(c2.getId(), ent);
313369

@@ -319,11 +375,13 @@ private TreeMap<String,EntityInfo> findCompoundsFromAlignment() {
319375
logger.debug("Adding chain {} to entity {}",c1.getId(),c2.getId());
320376
ent = chainIds2compounds.get(c2.getId());
321377
ent.addChain(c1);
378+
c1.setEntityInfo(ent);
322379
chainIds2compounds.put(c1.getId(), ent);
323380

324381
} else {
325382
logger.debug("Adding chain {} to entity {}",c2.getId(),c1.getId());
326383
ent.addChain(c2);
384+
c2.setEntityInfo(ent);
327385
chainIds2compounds.put(c2.getId(), ent);
328386

329387
}
@@ -347,13 +405,14 @@ private TreeMap<String,EntityInfo> findCompoundsFromAlignment() {
347405

348406
// anything not in a Compound will be its own Compound
349407
for (int i:polyChainIndices) {
350-
Chain c = allModels.get(0).get(i);
408+
Chain c = polyModels.get(0).get(i);
351409
if (!chainIds2compounds.containsKey(c.getId())) {
352410
logger.debug("Creating a 1-member Compound for chain {}",c.getId());
353411

354412
EntityInfo ent = new EntityInfo();
355413
ent.addChain(c);
356414
ent.setMolId(molId++);
415+
c.setEntityInfo(ent);
357416

358417
chainIds2compounds.put(c.getId(),ent);
359418
}

0 commit comments

Comments
 (0)