From d03b6673b76396d1b6146e0b3e76ac3f8cb1518a Mon Sep 17 00:00:00 2001 From: Jim Procter Date: Wed, 7 Feb 2018 13:10:18 +0000 Subject: [PATCH 1/1] JAL-2780 JAL-2781 first pass at failing test for incorrect colouring of structure after import and display of fragment of PDB 4IM2 --- .../structure/StructureSelectionManagerTest.java | 156 ++++++++++++++++++++ 1 file changed, 156 insertions(+) diff --git a/test/jalview/structure/StructureSelectionManagerTest.java b/test/jalview/structure/StructureSelectionManagerTest.java index 96d36ba..5b5c4a2 100644 --- a/test/jalview/structure/StructureSelectionManagerTest.java +++ b/test/jalview/structure/StructureSelectionManagerTest.java @@ -35,9 +35,11 @@ import jalview.datamodel.PDBEntry; import jalview.datamodel.Sequence; import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceI; +import jalview.ext.jmol.JmolCommands; import jalview.gui.AlignFrame; import jalview.gui.Desktop; import jalview.gui.JvOptionPane; +import jalview.gui.SequenceRenderer; import jalview.gui.StructureChooser; import jalview.io.DataSourceType; import jalview.io.FileLoader; @@ -181,6 +183,160 @@ public class StructureSelectionManagerTest extends Jalview2xmlBase assertEquals("ALA: 1 1gaqB", sf.getDescription()); } + /** + * Verify that RESNUM sequence features are present after creating a PDB + * mapping from a local file, then that everything stays in the same place + * when the file is viewed. The corner case is that 4IM2 is a fragment of a + * PDB file, which still includes the 'ID' field - a bug in Jalview 2.10.3 + * causes features, annotation and positions to be remapped to the wrong place + * on viewing the structure + */ + @Test(groups = { "Functional" }) + public void testMapping_EqualsFeatures() + { + SequenceI seq = new Sequence("4IM2|A", + "LDFCIRNIEKTVMGEISDIHTKLLRLSSSQGTIE"); + String P4IM2_MISSING = "examples/testdata/4IM2_missing.pdb"; + StructureSelectionManager sm = new StructureSelectionManager(); + sm.setProcessSecondaryStructure(true); + sm.setAddTempFacAnnot(true); + StructureFile pmap = sm.setMapping(true, new SequenceI[] { seq }, + new String[] + { null }, P4IM2_MISSING, + DataSourceType.FILE); + assertTrue(pmap != null); + + assertEquals(1, pmap.getSeqs().size()); + assertEquals("4IM2|A", pmap.getSeqs().get(0).getName()); + + List structuremap1 = new ArrayList( + sm.getMapping(P4IM2_MISSING)[0] + .getPDBResNumRanges(seq.getStart(), seq.getEnd())); + + /* + * Verify a RESNUM sequence feature in the PDBfile sequence + * LEU468 - start+0 + * VAL479 - start+11 + * MET486 - start+12 + * GLY496 - start+13 + * GLU516 - start+33 (last) + * + * Expect features and mapping to resolve to same residues. + * Also try creating a view and test again + * + */ + String[] feats = new String[] { "LEU", "468", "VAL", "479", "MET", + "486", "GLY", "496", "GLU", "516" }; + int[] offset = new int[] { 0, 11, 12, 13, 33 }; + + List fdesc = new ArrayList<>(); + for (int f = 0; f < feats.length; f += 2) + { + fdesc.add(feats[f] + ": " + feats[f + 1] + " 4im2A"); + } + SequenceI pdbseq = pmap.getSeqs().get(0); + verifySeqFeats(pdbseq, offset, fdesc); + + /// Now load as a view + + AlignFrame alf = new FileLoader(false).LoadFileWaitTillLoaded( + "examples/testdata/4IM2_missing.pdb", DataSourceType.FILE); + AlignmentI pdbal = alf.getViewport().getAlignment(); + SequenceI pdb_viewseq = pdbal.getSequenceAt(0); + assertEquals(pdb_viewseq.getSequenceAsString(), + seq.getSequenceAsString()); + // verify the feature location on the sequence when pdb imported as an + // alignment + verifySeqFeats(pdb_viewseq, offset, fdesc); + + + JalviewStructureDisplayI viewr = openStructureViaChooser(alf, + pdb_viewseq, "4IM2"); + + // and check all is good with feature location still + verifySeqFeats(pdb_viewseq, offset, fdesc); + + // finally check positional mapping for sequence and structure + PDBEntry pdbe = seq.getPDBEntry("4IM2"); + StructureSelectionManager apssm = alf.alignPanel + .getStructureSelectionManager(); + StructureMapping[] smap = apssm + .getMapping(pdbe.getFile()); + assertNotNull(smap); + assertNotNull(smap[0]); + // find the last position in the alignment sequence - this is not + // 'SequenceI.getEnd()' - which gets the last PDBRESNUM rather than + // SequenceI.getStart() + number of residues in file... + int realSeqEnd = pdb_viewseq.findPosition(pdb_viewseq.getLength()); + List ranges = smap[0].getPDBResNumRanges(pdb_viewseq.getStart(), + realSeqEnd); + assertEquals(structuremap1.size(), ranges.size()); + int tot_mapped = 0; + for (int p = 0; p < ranges.size(); p++) + { + assertArrayEquals(structuremap1.get(p), ranges.get(p)); + tot_mapped += 1 + (structuremap1.get(p)[1] - structuremap1.get(p)[0]); + } + + assertEquals(pdb_viewseq.getLength(), tot_mapped); + + int lastmappedp = StructureMapping.UNASSIGNED_VALUE; + for (int rp = pdb_viewseq.getStart(), rpEnd = pdb_viewseq + .findPosition(pdb_viewseq.getLength() - 1); rp <= rpEnd; rp++) + { + int mappedp = smap[0].getPDBResNum(rp); + if (mappedp != StructureMapping.UNASSIGNED_VALUE) + { + tot_mapped--; + if (lastmappedp == mappedp) + { + Assert.fail("Duplicate mapped position at " + rp + " (dupe = " + + mappedp + ")"); + } + } + } + + Assert.assertEquals(tot_mapped, 0, + "Different number of mapped residues compared to ranges of mapped residues"); + + // positional mapping to atoms for color by structure is still wrong, even + // though panel looks correct. + + StructureMappingcommandSet smcr[] = JmolCommands + .getColourBySequenceCommand(apssm, + new String[] + { pdbe.getFile() }, + new SequenceI[][] + { new SequenceI[] { pdb_viewseq } }, + new SequenceRenderer(alf.alignPanel.getAlignViewport()), + alf.alignPanel); + // Expected - all residues are white + for (StructureMappingcommandSet smm : smcr) + { + for (String c : smm.commands) + { + System.out.println(c); + } + } + + } + + private void verifySeqFeats(SequenceI pdbseq, int[] offset, + List fdesc) + { + for (int o = 0; o < offset.length; o++) + { + int res = pdbseq.findPosition(offset[o]); + List sf = pdbseq.getFeatures().findFeatures(res, res, + "RESNUM"); + assertEquals("Expected sequence feature at position " + res + "(" + + offset[o] + ")", 1, sf.size()); + assertEquals("Wrong description at " + res + "(" + offset[o] + ")", + fdesc.get(o), sf.get(0).getDescription()); + } + + } + @Test(groups= {"Network"}) public void testAssociatedMappingToSubSeq() throws Exception { -- 1.7.10.2