/*
* 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-12-01
*
*/
package org.biojava.nbio.structure;
import org.biojava.nbio.structure.align.util.AtomCache;
import org.biojava.nbio.structure.io.LocalPDBDirectory;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.util.NavigableMap;
import static org.junit.Assert.*;
import static org.junit.Assume.*;
/**
* A unit test for {@link org.biojava.nbio.structure.AtomPositionMap}.
* @author dmyerstu
*/
public class AtomPositionMapTest {
@Before
public void setUp() throws Exception {
cache = new AtomCache(); // TODO Should mock instead of depending on real data from AtomCache
cache.setObsoleteBehavior(LocalPDBDirectory.ObsoleteBehavior.FETCH_OBSOLETE);
}
private AtomCache cache;
/**
* Tests with no insertion codes.
* @throws StructureException
* @throws IOException
*/
@Test
public void testEasy() throws IOException, StructureException { // no insertion codes
// Straightforward case. Density for residues 25-777 (743 residues)
String pdbId = "1w0p";
int length = 93;
ResidueNumber start = new ResidueNumber("A", 25, null);
ResidueNumber end = new ResidueNumber("A", 117, null);
AtomPositionMap map = new AtomPositionMap(cache.getAtoms(pdbId));
NavigableMap<ResidueNumber,Integer> navMap = map.getNavMap();
for (ResidueNumber n : navMap.keySet()) {
assertEquals("An element is missing", map.getPosition(n).intValue(), navMap.get(n).intValue());
}
int realLength = map.getLength(start, end);
assertEquals("Real atom length is wrong", length, realLength);
}
@Test
public void testLengths() throws IOException, StructureException {
// Two identical chains, residues 1-68, no insertion codes or missing residues
String pdbId = "3w0e";
Atom[] atoms = cache.getAtoms(pdbId);
AtomPositionMap map = new AtomPositionMap(atoms);
// Double check that the chain length is correct
int chainAlen = cache.getStructure(pdbId).getPolyChainByPDB("A").getAtomGroups(GroupType.AMINOACID).size();
assumeTrue(68==chainAlen);
int len;
int start,end;// 0-based
// Single residue
start = 0;
end = 0;
len = map.getLength(new ResidueNumber("A",start+1,null), new ResidueNumber("A",end+1,null));
assertEquals("Bad length for ("+start+","+end+")",1, len);
len = map.getLength(start, end,"A");
assertEquals("Bad length for ("+start+","+end+")",1, len);
len = map.getLengthDirectional(start, end, "A");
assertEquals("Bad length for ("+start+","+end+")",1, len);
len = map.getLengthDirectional(end, start, "A");
assertEquals("Bad length for ("+start+","+end+")",1, len);
// Short range
start = 2;
end = 4;
len = map.getLength(new ResidueNumber("A",start+1,null), new ResidueNumber("A",end+1,null));
assertEquals("Bad length for ("+start+","+end+")",3, len);
len = map.getLength(start, end,"A");
assertEquals("Bad length for ("+start+","+end+")",3, len);
len = map.getLengthDirectional(start, end, "A");
assertEquals("Bad length for ("+start+","+end+")",3, len);
len = map.getLengthDirectional(end, start, "A");
assertEquals("Bad length for ("+start+","+end+")",-3, len);
//Full chain
start = 0;
end = chainAlen-1;
len = map.getLength(new ResidueNumber("A",start+1,null), new ResidueNumber("A",end+1,null));
assertEquals("Bad length for ("+start+","+end+")",chainAlen, len);
len = map.getLength(start, end,"A");
assertEquals("Bad length for ("+start+","+end+")",chainAlen, len);
len = map.getLengthDirectional(start, end, "A");
assertEquals("Bad length for ("+start+","+end+")",chainAlen, len);
len = map.getLengthDirectional(end, start, "A");
assertEquals("Bad length for ("+start+","+end+")",-chainAlen, len);
// Chain spanning
start = chainAlen-1;
end = chainAlen;
try {
len = map.getLength(new ResidueNumber("A",chainAlen,null), new ResidueNumber("B",1,null));
fail("Not the same chain");
} catch( IllegalArgumentException e) {}
len = map.getLength(start, end,"A");
assertEquals("Bad length for ("+start+","+end+")",1, len);
len = map.getLengthDirectional(start, end, "A");
assertEquals("Bad length for ("+start+","+end+")",1, len);
len = map.getLengthDirectional(end, start, "A");
assertEquals("Bad length for ("+start+","+end+")",-1, len);
len = map.getLengthDirectional(start,end, "B");
assertEquals("Bad length for ("+start+","+end+")",1, len);
start = chainAlen-2; //2 residues of A
end = chainAlen+2; // 3 residues of B
len = map.getLengthDirectional(start, end, "A");
assertEquals("Bad length for ("+start+","+end+")",2, len);
len = map.getLengthDirectional(end, start, "A");
assertEquals("Bad length for ("+start+","+end+")",-2, len);
len = map.getLengthDirectional(start, end, "B");
assertEquals("Bad length for ("+start+","+end+")",3, len);
len = map.getLengthDirectional(end, start, "B");
assertEquals("Bad length for ("+start+","+end+")",-3, len);
start = 0;
end = chainAlen;
try {
len = map.getLength(new ResidueNumber("A",start+1,null), new ResidueNumber("A",end+1,null));
fail("Residue found from the wrong chain");
} catch( IllegalArgumentException e) {
// end residue should be B1, not A142
}
// Chain Spanning
len = map.getLength(start, end,"B");
assertEquals("Bad length for ("+start+","+end+")",1, len);
len = map.getLengthDirectional(start, end, "B");
assertEquals("Bad length for ("+start+","+end+")",1, len);
len = map.getLengthDirectional(end, start, "B");
assertEquals("Bad length for ("+start+","+end+")",-1, len);
len = map.getLength(start, end,"A");
assertEquals("Bad length for ("+start+","+end+")",chainAlen, len);
len = map.getLengthDirectional(start, end, "A");
assertEquals("Bad length for ("+start+","+end+")",chainAlen, len);
len = map.getLengthDirectional(end, start, "A");
assertEquals("Bad length for ("+start+","+end+")",-chainAlen, len);
}
/**
* Tests with insertion codes.
* @throws StructureException
* @throws IOException
*/
@Test
public void testInsertionCodes() throws IOException, StructureException {
String pdbId = "1qdm";
// has 2 insertion code regions, lettered P and S, as well as disordered regions:
// 6P-26P,2-163,169-247,1S-37S,65S-104S,248-338
// Len:21, 162, 79, 37, 40, 91 = 430
AtomPositionMap map = new AtomPositionMap(cache.getAtoms(pdbId));
NavigableMap<ResidueNumber,Integer> navMap = map.getNavMap();
for (ResidueNumber n : navMap.keySet()) {
assertEquals("An element is missing", map.getPosition(n).intValue(), navMap.get(n).intValue());
}
int length1 = 60; // 2+37+21
int length2 = 132;// 2+37+40+53
ResidueNumber start = new ResidueNumber("A", 246, null);
ResidueNumber mid = new ResidueNumber("A", 85, 'S');
ResidueNumber end = new ResidueNumber("A", 300, null);
int realLength1 = map.getLength(start, mid);
assertEquals("Real atom length is wrong", length1, realLength1);
int realLength2 = map.getLength(start, end);
assertEquals("Real atom length is wrong", length2, realLength2);
int realLength = map.getLength(new ResidueNumber("A",6,'P'),new ResidueNumber("A",338,null));
assertEquals("Full length wrong",430,realLength);
}
@Test
public void testTrim() throws IOException, StructureException {
// Two identical chains, residues 1-68, no insertion codes or missing residues
String pdbId = "3w0e";
AtomPositionMap map = new AtomPositionMap(cache.getAtoms(pdbId));
ResidueRangeAndLength trimmed;
ResidueRange untrimmed;
untrimmed = new ResidueRange("A", "1", "68");
trimmed = map.trimToValidResidues(untrimmed);
assertEquals("Wrong start after trimming "+untrimmed,new ResidueNumber("A", 1, null), trimmed.getStart());
assertEquals("Wrong end after trimming "+untrimmed,new ResidueNumber("A", 68, null), trimmed.getEnd());
assertEquals("Wrong length after trimming "+untrimmed,68, trimmed.getLength());
untrimmed = new ResidueRange("A", "1", "1");
trimmed = map.trimToValidResidues(untrimmed);
assertEquals("Wrong start after trimming "+untrimmed,new ResidueNumber("A", 1, null), trimmed.getStart());
assertEquals("Wrong end after trimming "+untrimmed,new ResidueNumber("A", 1, null), trimmed.getEnd());
assertEquals("Wrong length after trimming "+untrimmed,1, trimmed.getLength());
untrimmed = new ResidueRange("A", "-1", "70");
trimmed = map.trimToValidResidues(untrimmed);
assertEquals("Wrong start after trimming "+untrimmed,new ResidueNumber("A", 1, null), trimmed.getStart());
assertEquals("Wrong end after trimming "+untrimmed,new ResidueNumber("A", 68, null), trimmed.getEnd());
assertEquals("Wrong length after trimming "+untrimmed,68, trimmed.getLength());
// Fully out of range
untrimmed = new ResidueRange("A", "-4", "-1");
trimmed = map.trimToValidResidues(untrimmed);
assertNull("Should be empty range "+untrimmed,trimmed);
// Start before end. Arguably should be invalid, but currently works
untrimmed = new ResidueRange("A", "4", "1");
trimmed = map.trimToValidResidues(untrimmed);
assertEquals("Wrong start after trimming "+untrimmed,new ResidueNumber("A", 4, null), trimmed.getStart());
assertEquals("Wrong end after trimming "+untrimmed,new ResidueNumber("A", 1, null), trimmed.getEnd());
assertEquals("Wrong length after trimming "+untrimmed,4, trimmed.getLength());
// However, doesn't work if the endpoints are invalid, since searches wrong direction
untrimmed = new ResidueRange("A", "4", "-1");
trimmed = map.trimToValidResidues(untrimmed);
assertNull("Should be empty range "+untrimmed,trimmed);
untrimmed = new ResidueRange("A", "70", "50");
trimmed = map.trimToValidResidues(untrimmed);
assertNull("Should be empty range "+untrimmed,trimmed);
}
@Test
public void testChains() throws IOException, StructureException {
String pdbId = "1qdm";
AtomPositionMap map = new AtomPositionMap(cache.getAtoms(pdbId));
ResidueNumber start,end;
try {
start = new ResidueNumber("A",6,'P');
end = new ResidueNumber("B",338,null);
map.getLength(start, end);
fail("Chain missmatch");
} catch(IllegalArgumentException e) {
// Expected
}
try {
start = new ResidueNumber("A",6,'P');
end = new ResidueNumber("B",338,null);
map.getLengthDirectional(start, end);
fail("Chain missmatch");
} catch(IllegalArgumentException e) {
// Expected
}
// With integers, only count matching chain atoms
start = new ResidueNumber("A",338,null);
end = new ResidueNumber("B",6,'P');
int len = map.getLength(map.getPosition(start),map.getPosition(end),"A");
assertEquals(1, len);
}
}