/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * * Created on 2012-11-20 * */ package org.biojava.nbio.structure; import org.biojava.nbio.structure.align.util.AtomCache; import org.biojava.nbio.structure.io.LocalPDBDirectory.ObsoleteBehavior; import org.junit.Before; import org.junit.Test; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import static org.junit.Assert.*; /** * A unit test for {@link ResidueRange}. * * @author dmyerstu * */ public class ResidueRangeTest { private AtomCache cache; @Before public void setUp() throws Exception { cache = new AtomCache(); // TODO Should mock instead of depending on // real data from AtomCache cache.setObsoleteBehavior(ObsoleteBehavior.FETCH_OBSOLETE); } @Test public void testWholeChainBasic() { String range = "B:"; ResidueRange rr = ResidueRange.parse(range); assertEquals("Wrong chain Id", "B", rr.getChainName()); assertNull("Start residue should be null", rr.getStart()); assertNull("End residue should be null", rr.getEnd()); } @Test public void testPartialChainWithMap() throws IOException, StructureException { String pdbId = "1cph"; AtomPositionMap map = new AtomPositionMap(cache.getAtoms(pdbId)); String range = "B:1-30"; ResidueRange rr = ResidueRangeAndLength.parse(range, map); ResidueNumber start = new ResidueNumber("B", 1, null); ResidueNumber end = new ResidueNumber("B", 30, null); assertEquals("Wrong chain Id", "B", rr.getChainName()); assertEquals("Wrong start", start, rr.getStart()); assertEquals("Wrong end", end, rr.getEnd()); } @Test public void testWholeChainWithMap() throws IOException, StructureException { String pdbId = "1cph"; AtomPositionMap map = new AtomPositionMap(cache.getAtoms(pdbId)); String range = "B:"; ResidueRange rr = ResidueRangeAndLength.parse(range, map); assertEquals("Wrong chain Id", "B", rr.getChainName()); assertEquals("Wrong start", new ResidueNumber("B",1,null),rr.getStart()); assertEquals("Wrong end", new ResidueNumber("B",30,null),rr.getEnd()); } /** * Tests creating ResidueRanges and calculating their lengths. */ @Test public void testWithLengths() throws IOException, StructureException { String[] ids = new String[] { "1w0p", "3qq3", "3chc", "2ei7" }; // more: // , // "2qbr" String[] chains = new String[] { "A", "B", "A", "L" }; ResidueNumber[] starts = new ResidueNumber[] { new ResidueNumber("A", 5, ' '), new ResidueNumber("B", 10, 's'), new ResidueNumber("A", 15, 'm'), new ResidueNumber("L", 44, ' ') }; ResidueNumber[] ends = new ResidueNumber[] { new ResidueNumber("A", 117, ' '), new ResidueNumber("B", 200, 's'), new ResidueNumber("A", 464, 'q'), new ResidueNumber("L", 254, 't') }; int[] lengths = new int[] { 117 - 5, 200 - 10, 111, 55 }; int totalLength = 0; List<ResidueRangeAndLength> ranges = new ArrayList<ResidueRangeAndLength>( ids.length); for (int i = 0; i < ids.length; i++) { ResidueRangeAndLength rr = new ResidueRangeAndLength(chains[i], starts[i], ends[i], lengths[i]); assertEquals("The chain is incorrect", chains[i], rr.getChainName()); assertEquals("The start is incorrect", starts[i], rr.getStart()); assertEquals("The end is incorrect", ends[i], rr.getEnd()); assertEquals("The length is incorrect", lengths[i], rr.getLength()); ranges.add(rr); totalLength += lengths[i]; assertEquals("Total length is wrong", totalLength, ResidueRangeAndLength.calcLength(ranges)); } } @Test public void testLengths() throws IOException, StructureException { String pdbId = "1w0p"; String rangeStr = "A:25-26"; Atom[] atoms = cache.getAtoms(pdbId); AtomPositionMap map = new AtomPositionMap(atoms); ResidueRangeAndLength range = ResidueRangeAndLength .parse(rangeStr, map); assertEquals(2, range.getLength()); } @Test public void testIterator() throws IOException, StructureException { String pdbId = "2eke"; String[] expected = new String[] { "C_1023", "C_1024", "C_1025", "C_1026", "C_1027", "C_1028", "C_1029", "C_1030", "C_1031", "C_1032", "C_1033", "C_1034", "C_1035", "C_1036", "C_1037", "C_1038", "C_1039", "C_1040", "C_1041", "C_1042", "C_1043", "C_1044", "C_1045", "C_1046", "C_1047", "C_1048", "C_1049", "C_1050", "C_1051", "C_1052", "C_1053", "C_1054", "C_1055", "C_1056", "C_1057", "C_1058", "C_1059", "C_1060", "C_1061", "C_1062", "C_1063" }; ResidueRange rr = ResidueRange.parse("C_1023-1063"); AtomPositionMap map = new AtomPositionMap(cache.getAtoms(pdbId)); Iterator<ResidueNumber> iter = rr.iterator(map); int i = 0; while (iter.hasNext()) { ResidueNumber rn = iter.next(); assertTrue(i<expected.length); assertEquals(expected[i], rn.printFull()); i++; } assertEquals(expected.length,i); } @Test public void testMultiIterator() throws IOException, StructureException { String pdbId = "1qdm"; String[] expected = new String[] { "A_3S", "A_4S", "A_5S", "A_6S", "A_7S", "A_8S", "A_9S", "A_10S", "A_11S", "A_12S", "A_13S", "A_14S", "A_15S", "A_16S", "A_17S", "A_18S", "A_19S", "A_20S", "A_21S", "A_22S", "A_23S", "A_24S", "A_25S", "A_26S", "A_27S", "A_28S", "A_29S", "A_30S", "A_31S", "A_32S", "A_33S", "A_34S", "A_35S", "A_36S", "A_37S", "A_65S", "A_66S", "A_67S", "A_68S", "A_69S", "A_70S", "A_71S", "A_72S", "A_73S", "A_74S", "A_75S", "A_76S", "A_77S", "A_78S", "A_79S", "A_80S", "A_81S", "A_82S", "A_83S", "A_84S", "A_85S", "A_86S", "A_87S", "A_88S", "A_89S", "A_90S", "A_91S", "A_92S", "A_93S", "A_94S", "A_95S", "A_96S", "A_97S", "A_98S", "A_99S" }; List<ResidueRange> rrs = ResidueRange .parseMultiple("A_3S-37S,A_65S-99S"); AtomPositionMap map = new AtomPositionMap(cache.getAtoms(pdbId)); Iterator<ResidueNumber> iter = ResidueRange.multiIterator(map, rrs); int i = 0; while (iter.hasNext()) { ResidueNumber rn = iter.next(); assertEquals(expected[i], rn.printFull()); i++; } } /** * Tests {@link ResidueRange#parseMultiple(String)}. */ @Test public void testParseAndEqual() { String rangeStr; List<ResidueRange> ranges; ResidueRange range; // String pdbId1 = "2eke"; rangeStr = "C_1023-1063,C_1064-1084"; ranges = ResidueRange.parseMultiple(rangeStr); assertEquals(new ResidueRange("C", new ResidueNumber("C", 1023, null), new ResidueNumber("C", 1063, null)), ranges.get(0)); assertEquals(new ResidueRange("C", new ResidueNumber("C", 1064, null), new ResidueNumber("C", 1084, null)), ranges.get(1)); // String pdbId = "1qdm"; rangeStr = "A_3S-37S,A_65S-99S"; ranges = ResidueRange.parseMultiple(rangeStr); assertEquals(new ResidueRange("A", new ResidueNumber("A", 3, 'S'), new ResidueNumber("A", 37, 'S')), ranges.get(0)); assertEquals(new ResidueRange("A", new ResidueNumber("A", 65, 'S'), new ResidueNumber("A", 99, 'S')), ranges.get(1)); // Multi-character chains rangeStr = "AB,A1,ABCD_1-55,NotAG00dID:-5-1R"; ranges = ResidueRange.parseMultiple(rangeStr); range = ranges.get(0); assertEquals("Error parsing " + rangeStr, "AB", range.getChainName()); assertNull("Error parsing " + rangeStr, range.getStart()); assertNull("Error parsing " + rangeStr, range.getEnd()); range = ranges.get(1); assertEquals("Error parsing " + rangeStr, "A1", range.getChainName()); assertNull("Error parsing " + rangeStr, range.getStart()); assertNull("Error parsing " + rangeStr, range.getEnd()); range = ranges.get(2); assertEquals("Error parsing " + rangeStr, "ABCD", range.getChainName()); assertEquals("Error parsing " + rangeStr, new ResidueNumber("ABCD", 1, null), range.getStart()); assertEquals("Error parsing " + rangeStr, new ResidueNumber("ABCD", 55, null), range.getEnd()); range = ranges.get(3); assertEquals("Error parsing " + rangeStr, "NotAG00dID", range.getChainName()); assertEquals("Error parsing " + rangeStr, new ResidueNumber( "NotAG00dID", -5, null), range.getStart()); assertEquals("Error parsing " + rangeStr, new ResidueNumber( "NotAG00dID", 1, 'R'), range.getEnd()); // Wildcard chains rangeStr = "_,__,_:1-5,_:+1-+5"; ranges = ResidueRange.parseMultiple(rangeStr); range = ranges.get(0); assertEquals("Error parsing " + rangeStr, "_", range.getChainName()); assertNull("Error parsing " + rangeStr, range.getStart()); assertNull("Error parsing " + rangeStr, range.getEnd()); range = ranges.get(1); assertEquals("Error parsing " + rangeStr, "_", range.getChainName()); assertNull("Error parsing " + rangeStr, range.getStart()); assertNull("Error parsing " + rangeStr, range.getEnd()); range = ranges.get(2); assertEquals("Error parsing " + rangeStr, "_", range.getChainName()); assertEquals("Error parsing " + rangeStr, new ResidueNumber("_", 1, null), range.getStart()); assertEquals("Error parsing " + rangeStr, new ResidueNumber("_", 5, null), range.getEnd()); range = ranges.get(3); assertEquals("Error parsing " + rangeStr, "_", range.getChainName()); assertEquals("Error parsing " + rangeStr, new ResidueNumber("_", 1, null), range.getStart()); assertEquals("Error parsing " + rangeStr, new ResidueNumber("_", 5, null), range.getEnd()); } @Test(expected=IllegalArgumentException.class) public void testBadSyntax() throws IOException, StructureException { ResidueRange.parse("-"); } @Test public void testPartialRange() throws IOException, StructureException { String rangeStr = "C_1023-"; ResidueRange range = ResidueRange.parse(rangeStr); assertEquals(rangeStr,1023,(int)range.getStart().getSeqNum()); assertNull(rangeStr,range.getEnd()); rangeStr = "C_-"; range = ResidueRange.parse(rangeStr); assertNull(rangeStr,range.getStart()); assertNull(rangeStr,range.getEnd()); rangeStr = "A_-+55"; range = ResidueRange.parse(rangeStr); assertNull(rangeStr,range.getStart()); assertEquals(rangeStr,55,(int)range.getEnd().getSeqNum()); } @Test public void testPartialRangeLength() throws IOException, StructureException { AtomPositionMap map = new AtomPositionMap(cache.getAtoms("2eke")); String rangeStr = "C_1023-"; ResidueRangeAndLength range = ResidueRangeAndLength.parse(rangeStr, map); assertEquals(rangeStr,1023,(int)range.getStart().getSeqNum()); assertEquals(rangeStr,1095,(int)range.getEnd().getSeqNum()); assertEquals(rangeStr, 73, range.getLength()); } /** * Tests * {@link org.biojava.nbio.structure.ResidueRangeAndLength#parseMultiple(String, org.biojava.nbio.structure.AtomPositionMap)} * . * * @throws StructureException * @throws IOException */ @Test public void testParseAndEqualWithLengths() throws IOException, StructureException { String rangeStr; List<ResidueRangeAndLength> ranges; ResidueRangeAndLength range; AtomPositionMap map; String pdbId = "2eke"; map = new AtomPositionMap(cache.getAtoms(pdbId)); rangeStr = "C_1023-1063,C_1064-1084,C";//C is 105-112,1013-1095 ranges = ResidueRangeAndLength.parseMultiple(rangeStr, map); assertEquals(new ResidueRangeAndLength("C", new ResidueNumber("C", 1023, null), new ResidueNumber("C", 1063, null), 1063 - 1023+1), ranges.get(0)); assertEquals(new ResidueRangeAndLength("C", new ResidueNumber("C", 1064, null), new ResidueNumber("C", 1084, null), 1084 - 1064+1), ranges.get(1)); assertEquals(new ResidueRangeAndLength("C", new ResidueNumber("C", 105, null), new ResidueNumber("C", 1095, null), 91), ranges.get(2)); // Wildcard chains pdbId = "4r61"; // A:8-52,58-109,119-161 map = new AtomPositionMap(cache.getAtoms(pdbId)); rangeStr = "_,__,_:52-58"; ranges = ResidueRangeAndLength.parseMultiple(rangeStr, map); range = ranges.get(0); assertEquals("Error parsing " + rangeStr, "A", range.getChainName()); assertEquals("Error parsing " + rangeStr, new ResidueNumber("A",8,null),range.getStart()); assertEquals("Error parsing " + rangeStr, new ResidueNumber("A",161,null),range.getEnd()); range = ranges.get(1); assertEquals("Error parsing " + rangeStr, "A", range.getChainName()); assertEquals("Error parsing " + rangeStr, new ResidueNumber("A",8,null),range.getStart()); assertEquals("Error parsing " + rangeStr, new ResidueNumber("A",161,null),range.getEnd()); range = ranges.get(2); assertEquals("Error parsing " + rangeStr, "A", range.getChainName()); assertEquals("Error parsing " + rangeStr, new ResidueNumber("A", 52,null), range.getStart()); assertEquals("Error parsing " + rangeStr, new ResidueNumber("A", 58,null), range.getEnd()); // wildcards not converted without the map ResidueRange range2 = ResidueRange.parse("_"); assertEquals("Error parsing " + rangeStr, "_", range2.getChainName()); assertNull("Error parsing " + rangeStr,range2.getStart()); assertNull("Error parsing " + rangeStr,range2.getEnd()); } @Test public void testRangeRegex() { // Valid ranges String[] yes = new String[] { "A_", "A:", "ABC:", "abc:", "A_5-100", "A_5-100S", "A_5S-100", "A_5S-100S", "A_-5-100", "A_-5--100", "A_-5S--100S", "ABC:-5--200S", "A", "ABCD", "A_1", "A1", // valid multi-char chain name "3A:1-100", // Weird chain name "_", "_:1-10", "__-2--1", "__", // catch-all chain "A:-3-+1","A:-3-+1","A:+1-6", // Positive numbers ok, although weird "A:1-","A:1S-","A:--5","A:-+5", // Partial ranges }; for (String s : yes) { assertTrue(s + " was not considered a valid range format", ResidueRange.RANGE_REGEX.matcher(s).matches()); } // invalid ranges String[] no = new String[] { "A_1-100-", "", "-", "___", "__:","A_-10-1000_", }; for (String s : no) { assertFalse(s + " was considered a valid range format", ResidueRange.RANGE_REGEX.matcher(s).matches()); } } @Test public void testTerminalSymbols() { String rangeStr; ResidueRange range; rangeStr = "A:1-$"; range = ResidueRange.parse(rangeStr); assertEquals(rangeStr,1,(int)range.getStart().getSeqNum()); assertNull(rangeStr,range.getEnd()); rangeStr = "A:^-1"; range = ResidueRange.parse(rangeStr); assertNull(rangeStr,range.getStart()); assertEquals(rangeStr,1,(int)range.getEnd().getSeqNum()); rangeStr = "A:^-$"; range = ResidueRange.parse(rangeStr); assertNull(rangeStr,range.getStart()); assertNull(rangeStr,range.getEnd()); } }