/*
* 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/
*
*/
package org.biojava.nbio.structure;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.util.List;
import org.biojava.nbio.structure.align.util.AtomCache;
import org.biojava.nbio.structure.contact.StructureInterface;
import org.biojava.nbio.structure.contact.StructureInterfaceList;
import org.biojava.nbio.structure.io.FileParsingParameters;
import org.biojava.nbio.structure.xtal.CrystalBuilder;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TestStructureCrossReferences {
private static final Logger logger = LoggerFactory.getLogger(TestStructureCrossReferences.class);
private static final String PDBCODE1 = "1smt";
private static final String PDBCODE2 = "2mre";
@Test
public void testCrossReferencesMmCif() throws IOException, StructureException {
boolean emptySeqRes = true;
AtomCache cache = new AtomCache();
cache.setUseMmCif(true);
FileParsingParameters params = new FileParsingParameters();
params.setAlignSeqRes(false); // Store empty seqres groups.
cache.setFileParsingParams(params);
StructureIO.setAtomCache(cache);
Structure structure = StructureIO.getStructure(PDBCODE1);
//System.out.println("Testing references in mmCIF loading with NO alignSeqRes");
doFullTest(structure, emptySeqRes);
structure = StructureIO.getStructure(PDBCODE2); // an NMR entry with 2 chains
doFullTest(structure, emptySeqRes);
}
@Test
public void testCrossReferencesMmCifAlignSeqRes() throws IOException, StructureException {
boolean emptySeqRes = false;
AtomCache cache = new AtomCache();
cache.setUseMmCif(true);
FileParsingParameters params = new FileParsingParameters();
params.setAlignSeqRes(true);
cache.setFileParsingParams(params);
StructureIO.setAtomCache(cache);
Structure structure = StructureIO.getStructure(PDBCODE1);
//System.out.println("Testing references in mmCIF loading with alignSeqRes");
doFullTest(structure, emptySeqRes);
structure = StructureIO.getStructure(PDBCODE2); // an NMR entry with 2 chains
doFullTest(structure, emptySeqRes);
}
@Test
public void testCrossReferencesPdb() throws IOException, StructureException {
boolean emptySeqRes = true;
AtomCache cache = new AtomCache();
cache.setUseMmCif(false);
FileParsingParameters params = new FileParsingParameters();
params.setAlignSeqRes(false); // Store empty seqres groups
cache.setFileParsingParams(params);
StructureIO.setAtomCache(cache);
Structure structure = StructureIO.getStructure(PDBCODE1);
doFullTest(structure, emptySeqRes);
structure = StructureIO.getStructure(PDBCODE2); // an NMR entry with 2 chains
doFullTest(structure, emptySeqRes);
}
@Test
public void testCrossReferencesPdbAlignSeqRes() throws IOException, StructureException {
boolean emptySeqRes = false;
AtomCache cache = new AtomCache();
cache.setUseMmCif(false);
FileParsingParameters params = new FileParsingParameters();
params.setAlignSeqRes(true);
cache.setFileParsingParams(params);
StructureIO.setAtomCache(cache);
//System.out.println("Testing references in PDB loading with alignSeqRes");
Structure structure = StructureIO.getStructure(PDBCODE1);
doFullTest(structure, emptySeqRes);
structure = StructureIO.getStructure(PDBCODE2); // an NMR entry with 2 chains
doFullTest(structure, emptySeqRes);
}
//@Test
public void testCrossReferencesRawFile() throws IOException, StructureException {
// TODO implement
}
private void doFullTest(Structure structure, boolean emptySeqRes) throws StructureException {
//System.out.println("Testing references in original structure");
testStructureRefs(structure, emptySeqRes);
logger.debug("Original structure mem hashCode: {}",System.identityHashCode(structure));
Structure structureCopy = structure.clone();
logger.debug("Clone structure mem hashCode: {}",System.identityHashCode(structureCopy));
assertNotSame(structure, structureCopy);
//System.out.println("Testing references in cloned structure");
testStructureRefs(structureCopy, emptySeqRes);
logger.debug("Original structure mem hashCode after cloning: {}",System.identityHashCode(structure));
//System.out.println("Testing references in original structure after having cloned it");
// we test again the original after cloning it, perhaps some references were mixed while cloning
// there is a bug in ChainImpl.clone() that mixes them up!
testStructureRefs(structure, emptySeqRes);
//System.out.println("Testing references of chain clones");
for (Chain c:structure.getChains()) {
Chain clonedChain = (Chain) c.clone();
testChainRefs(clonedChain, emptySeqRes);
}
//System.out.println("Testing references in atom arrays");
for (Chain c:structure.getChains()) {
Atom[] atomArray = StructureTools.getAllAtomArray(c);
testAtomArrayRefs(atomArray, c);
}
CrystalBuilder cb = new CrystalBuilder(structure);
StructureInterfaceList interfaces = cb.getUniqueInterfaces();
for (StructureInterface interf:interfaces) {
testInterfaceRefs(structure, interf);
}
//System.out.println("Testing references in original structure after getUniqueInterfaces");
testStructureRefs(structure, emptySeqRes);
}
private void testStructureRefs(Structure s, boolean emptySeqRes) throws StructureException {
// structure, chain, group, atom linking
for (Chain c:s.getChains()) {
logger.debug("Expected parent structure mem hashCode: {}",System.identityHashCode(s));
logger.debug("Actual parent structure mem hashCode: {}",System.identityHashCode(c.getStructure()));
assertSame(s, c.getStructure());
testChainRefs(c, emptySeqRes);
}
// compounds linking
for (EntityInfo compound:s.getEntityInfos()) {
for (Chain c:compound.getChains()) {
assertSame(compound, c.getEntityInfo());
int count = 0;
for (int modelNr=0;modelNr<s.nrModels();modelNr++) {
// the chain must be matched by 1 and only 1 chain from all models
Chain cFromStruc = s.getChain(c.getId(), modelNr);
if (cFromStruc==c) count++;
}
assertEquals("Only 1 chain must match the compound chain for all models",1,count);
}
}
}
private void testChainRefs(Chain c, boolean emptySeqRes) {
assertNotNull(c.getEntityInfo());
for (Group g:c.getAtomGroups()) {
assertSame("Failed parent chain for group "+g.toString(), c, g.getChain());
for (Atom a:g.getAtoms()) {
assertSame(g, a.getGroup());
assertSame(c, a.getGroup().getChain());
}
// the SEQRES groups should contain a reference to each and every ATOM group
// (of course they will also contain some extra groups: those that are only in SEQRES)
if (c.getSeqResGroups().size()>0) {
// we don't want to test hetatoms that are most likely outside of the seqres defined chains
if (g.getType() == GroupType.HETATM) continue;
// Only test for expected Atom(s) if we parsed Atoms into Structure.
if (!emptySeqRes)
assertTrue("SeqResGroups should contain ATOM group "+g.toString(),
containsReference(g, c.getSeqResGroups()) );
}
}
for (Group g:c.getSeqResGroups()) {
// When not aligned, this can be different.
if (!emptySeqRes)
assertSame("Failed parent chain for group "+g.toString(), c, g.getChain());
for (Atom a:g.getAtoms()) {
assertSame(g, a.getGroup());
assertSame(c, a.getGroup().getChain());
}
}
}
private void testAtomArrayRefs(Atom[] atoms, Chain c) {
for (Atom a:atoms) {
//"Not same: "+c.getChainID()+" ("+c.getAtomLength()+" atomLength, "+c.getSeqResLength()+" seqresLength)"+" | "+a.getGroup().getChain().getChainID()+" ("+a.getGroup().getChain().getAtomLength()+" atomLength, "+a.getGroup().getChain().getSeqResLength()+" seqresLength)"
assertSame(c, a.getGroup().getChain());
}
}
private void testInterfaceRefs(Structure s, StructureInterface i) throws StructureException {
for (Atom a:i.getMolecules().getFirst()) {
assertNotNull(a.getGroup().getChain().getEntityInfo());
}
for (Atom a:i.getMolecules().getSecond()) {
assertNotNull(a.getGroup().getChain().getEntityInfo());
}
}
private static boolean containsReference(Group g, List<Group> list) {
for (Group group:list) {
if (group==g) return true;
}
return false;
}
}