diff --git a/biojava3-structure/src/main/java/org/biojava/bio/structure/StructureTools.java b/biojava3-structure/src/main/java/org/biojava/bio/structure/StructureTools.java index e39e53ed9f..df94cb3d67 100644 --- a/biojava3-structure/src/main/java/org/biojava/bio/structure/StructureTools.java +++ b/biojava3-structure/src/main/java/org/biojava/bio/structure/StructureTools.java @@ -819,9 +819,15 @@ public static final Structure getSubRanges(Structure s, String ranges ) String chainId = matcher.group(1); Chain chain; - if(chainId.equals("_") && struc.size() == 1) { + if(chainId.equals("_") ) { // Handle special case of "_" chain for single-chain proteins chain = struc.getChain(0); + + if(struc.size() != 1) { + // SCOP 1.71 uses this for some proteins with multiple chains + // Print a warning in this ambiguous case + System.err.format("WARNING multiple possible chains match '_'. Using chain %s.%n",chain.getChainID()); + } } else { // Explicit chain chain = struc.getChainByPDB(chainId); diff --git a/biojava3-structure/src/main/java/org/biojava/bio/structure/io/PDBFileParser.java b/biojava3-structure/src/main/java/org/biojava/bio/structure/io/PDBFileParser.java index d4ff86386c..02553f1327 100644 --- a/biojava3-structure/src/main/java/org/biojava/bio/structure/io/PDBFileParser.java +++ b/biojava3-structure/src/main/java/org/biojava/bio/structure/io/PDBFileParser.java @@ -21,6 +21,7 @@ */ package org.biojava.bio.structure.io; +import static java.lang.Math.min; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; @@ -380,39 +381,48 @@ private Group getNewGroup(String recordName,Character aminoCode1, String aminoCo private void pdb_HEADER_Handler(String line) { //System.out.println(line); - String classification = line.substring (10, 50).trim() ; - String deposition_date = line.substring (50, 59).trim() ; - String pdbCode = line.substring (62, 66).trim() ; + String classification = null; + String deposition_date = null; + String pdbCode = null; - pdbId = pdbCode; - if (DEBUG) { - System.out.println("Parsing entry " + pdbId); + int len = line.trim().length(); + if(len > 10) { + classification = line.substring (10, min(len,50)).trim() ; + pdbHeader.setClassification(classification); } + if(len > 50) { + deposition_date = line.substring (50, min(len,59)).trim() ; + try { + Date dep = dateFormat.parse(deposition_date); + pdbHeader.setDepDate(dep); + + } catch (ParseException e){ + logger.fine("Could not parse deposition date string '"+deposition_date+"'. Will continue without deposition date"); + } + } + if(len > 62) { + pdbCode = line.substring (62, min(len,66)).trim() ; + pdbId = pdbCode; + if (DEBUG) { + System.out.println("Parsing entry " + pdbId); + } + + structure.setPDBCode(pdbCode); + pdbHeader.setIdCode(pdbCode); + } + //*really* old files (you'll need to hunt to find these as they //should have been remediated) have headers like below. Plus the //pdbId at positions 72-76 is present in every line //HEADER PROTEINASE INHIBITOR (TRYPSIN) 05-OCT-84 5PTI 5PTI 3 //HEADER TRANSFERASE (ACYLTRANSFERASE) 02-SEP-92 1LAC 1LAC 2 - if (line.trim().length() > 66) { + if (len > 66) { if (pdbId.equals(line.substring (72, 76))){ isLegacyFormat = true; System.out.println(pdbId + " is a LEGACY entry - this will most likely not parse correctly."); } } - structure.setPDBCode(pdbCode); - - pdbHeader.setIdCode(pdbCode); - pdbHeader.setClassification(classification); - - - try { - Date dep = dateFormat.parse(deposition_date); - pdbHeader.setDepDate(dep); - - } catch (ParseException e){ - logger.fine("Could not parse deposition date string '"+deposition_date+"'. Will continue without deposition date"); - } } diff --git a/biojava3-structure/src/main/java/org/biojava/bio/structure/scop/ScopInstallation.java b/biojava3-structure/src/main/java/org/biojava/bio/structure/scop/ScopInstallation.java index f9546d9903..eb83d6fe7e 100644 --- a/biojava3-structure/src/main/java/org/biojava/bio/structure/scop/ScopInstallation.java +++ b/biojava3-structure/src/main/java/org/biojava/bio/structure/scop/ScopInstallation.java @@ -531,10 +531,10 @@ private void parseComments(BufferedReader buffer) throws IOException { String line = null; while ((line = buffer.readLine ()) != null) { if (line.startsWith("#")) continue; - String[] parts = line.split(" ! "); + String[] parts = line.split("!"); int sunId = -1; try { - sunId = Integer.parseInt(parts[0]); + sunId = Integer.parseInt(parts[0].trim()); } catch (RuntimeException e) { e.printStackTrace(); continue; @@ -545,7 +545,10 @@ private void parseComments(BufferedReader buffer) throws IOException { } List comments = new ArrayList(parts.length - 1); for (int i = 1; i < parts.length; i++) { - comments.add(parts[i]); + String trimmed = parts[i].trim(); + if( !trimmed.isEmpty() ) { + comments.add(trimmed); + } } commentsMap.put(sunId, comments); } diff --git a/biojava3-structure/src/test/java/org/biojava/bio/structure/align/util/AtomCacheTest.java b/biojava3-structure/src/test/java/org/biojava/bio/structure/align/util/AtomCacheTest.java index 6d82fabbbb..ed11c1438b 100644 --- a/biojava3-structure/src/test/java/org/biojava/bio/structure/align/util/AtomCacheTest.java +++ b/biojava3-structure/src/test/java/org/biojava/bio/structure/align/util/AtomCacheTest.java @@ -32,6 +32,7 @@ import org.biojava.bio.structure.Structure; import org.biojava.bio.structure.StructureException; import org.biojava.bio.structure.StructureTools; +import org.biojava.bio.structure.scop.ScopDatabase; import org.biojava.bio.structure.scop.ScopFactory; import org.junit.Before; import org.junit.Test; @@ -118,4 +119,22 @@ public void testGetStructureForDomain3() throws IOException, StructureException assertEquals(1, ligandsE.size()); } + /** + * Test parsing of chain-less ranges (present in SCOP < 1.73) + * @throws IOException + * @throws StructureException + */ + @Test + public void testGetStructureForChainlessDomains() throws IOException, StructureException { + ScopDatabase scop = ScopFactory.getSCOP(ScopFactory.VERSION_1_71); // Uses the range '1-135' without a chain + Structure structure = cache.getStructureForDomain("d1hcy_1",scop); + assertEquals(1, structure.getChains().size()); + Chain a = structure.getChainByPDB("A"); + int expectedLengthA = 135+4; + assertEquals(expectedLengthA, a.getAtomGroups().size()); + List ligandsE = StructureTools.filterLigands(a.getAtomGroups()); + assertEquals(4, ligandsE.size()); + + } + } diff --git a/integrationtest/src/test/java/org/biojava/structure/test/scop/ScopDatabaseTest.java b/integrationtest/src/test/java/org/biojava/structure/test/scop/ScopDatabaseTest.java index c6c0163d3a..d62d9304c6 100644 --- a/integrationtest/src/test/java/org/biojava/structure/test/scop/ScopDatabaseTest.java +++ b/integrationtest/src/test/java/org/biojava/structure/test/scop/ScopDatabaseTest.java @@ -24,13 +24,10 @@ package org.biojava.structure.test.scop; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; import java.util.List; +import java.util.regex.Pattern; import org.biojava.bio.structure.scop.ScopCategory; import org.biojava.bio.structure.scop.ScopDatabase; @@ -102,7 +99,7 @@ public void traverseHierarchy() desc = scop.getScopDescriptionBySunid(node.getSunid()); assertEquals(tag,46487,node.getSunid()); assertEquals(tag,"-",desc.getName()); - assertEquals(tag,"Human (Homo sapiens) [TaxId: 9606]",desc.getDescription()); + assertTrue(tag,Pattern.matches("Human \\(Homo sapiens\\)( \\[TaxId: 9606\\])?",desc.getDescription())); assertEquals(tag,"a.1.1.2",desc.getClassificationId()); node = scop.getScopNode(node.getParentSunid()); @@ -206,13 +203,18 @@ public void testComments() { //TODO add additional version checks, since comments change a lot - if(scop.getScopVersion().compareToIgnoreCase( ScopFactory.VERSION_1_75) <= 0 ) { + if(scop.getScopVersion().compareToIgnoreCase( ScopFactory.VERSION_1_71) >= 0 ) { + comments = scop.getComments(15016); + assertEquals(tag+"Wrong number of comments", 1, comments.size()); + assertEquals(tag+"Wrong comment", "complexed with cmo, hem", comments.get(0).trim()); + } + if(scop.getScopVersion().compareToIgnoreCase( ScopFactory.VERSION_1_75) >= 0 ) { // Note: only tested so far with 1.75, so may need some modification for earlier versions comments = scop.getComments(127355); assertEquals(tag+"Wrong number of comments", 2, comments.size()); assertEquals(tag+"Wrong comment", "automatically matched to d2hbia_", comments.get(0).trim()); - assertEquals(tag+"Wrong comment", "complexed with hem; mutant", comments.get(1).trim()); + assertTrue(tag+"Wrong comment", Pattern.matches("complexed with hem(; mutant)?", comments.get(1).trim())); } if(scop.getScopVersion().compareToIgnoreCase( ScopFactory.VERSION_1_75) == 0 ) { comments = scop.getComments(160555); diff --git a/integrationtest/src/test/java/org/biojava/structure/test/scop/ScopInstallationTest.java b/integrationtest/src/test/java/org/biojava/structure/test/scop/ScopInstallationTest.java index aa91f952d2..834fda7759 100644 --- a/integrationtest/src/test/java/org/biojava/structure/test/scop/ScopInstallationTest.java +++ b/integrationtest/src/test/java/org/biojava/structure/test/scop/ScopInstallationTest.java @@ -40,36 +40,37 @@ @RunWith(Parameterized.class) public class ScopInstallationTest extends ScopDatabaseTest { - public ScopInstallationTest(String tag,ScopDatabase scop) { - super(tag,scop); - } + public ScopInstallationTest(String tag,ScopDatabase scop) { + super(tag,scop); + } - //@Parameters - @Parameters(name="{0}") - public static Collection availableDatabases() { - ArrayList databases = new ArrayList(); - ScopInstallation scop; + //@Parameters + @Parameters(name="{0}") + public static Collection availableDatabases() { + ArrayList databases = new ArrayList(); + ScopInstallation scop; - for(String version : new String[] { - ScopFactory.VERSION_1_75, - ScopFactory.VERSION_1_73, - }) { - scop = new ScopInstallation(); - scop.setScopVersion(version); - - // Don't fail if the server is down - boolean reachable = false; - for(ScopMirror mirror: scop.getMirrors()) { - if(mirror.isReachable()) { - reachable = true; - break; - } - } - Assume.assumeTrue("SCOP server is currently unreachable.",reachable); - - databases.add(new Object[] {version, scop}); - } - return databases; - } + for(String version : new String[] { + ScopFactory.VERSION_1_75, + ScopFactory.VERSION_1_73, + ScopFactory.VERSION_1_71, + }) { + scop = new ScopInstallation(); + scop.setScopVersion(version); + + // Don't fail if the server is down + boolean reachable = false; + for(ScopMirror mirror: scop.getMirrors()) { + if(mirror.isReachable()) { + reachable = true; + break; + } + } + Assume.assumeTrue("SCOP server is currently unreachable.",reachable); + + databases.add(new Object[] {version, scop}); + } + return databases; + } }