/* * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) * Copyright (C) $$Year-Rel$$ The Jalview Authors * * This file is part of Jalview. * * Jalview is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation, either version 3 * of the License, or (at your option) any later version. * * Jalview is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Jalview. If not, see . * The Jalview Authors are detailed in the 'AUTHORS' file. */ package jalview.analysis.scoremodels; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; import jalview.api.analysis.ScoreModelI; import jalview.api.analysis.SimilarityParamsI; import jalview.datamodel.Alignment; import jalview.datamodel.AlignmentI; import jalview.datamodel.AlignmentView; import jalview.datamodel.Sequence; import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceI; import jalview.gui.AlignFrame; import jalview.gui.AlignViewport; import jalview.gui.JvOptionPane; import jalview.io.DataSourceType; import jalview.io.FileLoader; import jalview.math.MatrixI; import java.util.Arrays; import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; public class FeatureDistanceModelTest { @BeforeClass(alwaysRun = true) public void setUpJvOptionPane() { JvOptionPane.setInteractiveMode(false); JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION); } public static String alntestFile = "FER1_MESCR/72-76 DVYIL\nFER1_SPIOL/71-75 DVYIL\nFER3_RAPSA/21-25 DVYVL\nFER1_MAIZE/73-77 DVYIL\n"; int[] sf1 = new int[] { 74, 74, 73, 73, 23, 23, -1, -1 }; int[] sf2 = new int[] { -1, -1, 74, 75, -1, -1, 76, 77 }; int[] sf3 = new int[] { -1, -1, -1, -1, -1, -1, 76, 77 }; /** *
   * Load test alignment and add features to sequences: 
   *      FER1_MESCR FER1_SPIOL FER3_RAPSA FER1_MAIZE 
   *  sf1     X          X          X  
   *  sf2                X                     X 
   *  sf3                                      X
   * 
* * @return */ public AlignFrame getTestAlignmentFrame() { AlignFrame alf = new FileLoader(false).LoadFileWaitTillLoaded( alntestFile, DataSourceType.PASTE); AlignmentI al = alf.getViewport().getAlignment(); Assert.assertEquals(al.getHeight(), 4); Assert.assertEquals(al.getWidth(), 5); for (int i = 0; i < 4; i++) { SequenceI ds = al.getSequenceAt(i).getDatasetSequence(); if (sf1[i * 2] > 0) { ds.addSequenceFeature(new SequenceFeature("sf1", "sf1", sf1[i * 2], sf1[i * 2 + 1], "sf1")); } if (sf2[i * 2] > 0) { ds.addSequenceFeature(new SequenceFeature("sf2", "sf2", sf2[i * 2], sf2[i * 2 + 1], "sf2")); } if (sf3[i * 2] > 0) { ds.addSequenceFeature(new SequenceFeature("sf3", "sf3", sf3[i * 2], sf3[i * 2 + 1], "sf3")); } } alf.setShowSeqFeatures(true); alf.getFeatureRenderer().setVisible("sf1"); alf.getFeatureRenderer().setVisible("sf2"); alf.getFeatureRenderer().setVisible("sf3"); alf.getFeatureRenderer().findAllFeatures(true); Assert.assertEquals(alf.getFeatureRenderer().getDisplayedFeatureTypes() .size(), 3, "Number of feature types"); assertTrue(alf.getCurrentView().areFeaturesDisplayed()); return alf; } @Test(groups = { "Functional" }) public void testFeatureScoreModel() throws Exception { AlignFrame alf = getTestAlignmentFrame(); ScoreModelI sm = new FeatureDistanceModel(); sm = ScoreModels.getInstance().getScoreModel(sm.getName(), alf.getCurrentView().getAlignPanel()); alf.selectAllSequenceMenuItem_actionPerformed(null); MatrixI dm = sm.findDistances( alf.getViewport().getAlignmentView(true), SimilarityParams.Jalview); assertEquals(dm.getValue(0, 2), 0d, "FER1_MESCR (0) should be identical with RAPSA (2)"); assertTrue(dm.getValue(0, 1) > dm.getValue(0, 2), "FER1_MESCR (0) should be further from SPIOL (1) than it is from RAPSA (2)"); } @Test(groups = { "Functional" }) public void testFeatureScoreModel_hiddenFirstColumn() throws Exception { AlignFrame alf = getTestAlignmentFrame(); // hiding first two columns shouldn't affect the tree alf.getViewport().hideColumns(0, 1); ScoreModelI sm = new FeatureDistanceModel(); sm = ScoreModels.getInstance().getScoreModel(sm.getName(), alf.getCurrentView().getAlignPanel()); alf.selectAllSequenceMenuItem_actionPerformed(null); MatrixI dm = sm.findDistances( alf.getViewport().getAlignmentView(true), SimilarityParams.Jalview); assertEquals(dm.getValue(0, 2), 0d, "FER1_MESCR (0) should be identical with RAPSA (2)"); assertTrue(dm.getValue(0, 1) > dm.getValue(0, 2), "FER1_MESCR (0) should be further from SPIOL (1) than it is from RAPSA (2)"); } @Test(groups = { "Functional" }) public void testFeatureScoreModel_HiddenColumns() throws Exception { AlignFrame alf = getTestAlignmentFrame(); // hide columns and check tree changes alf.getViewport().hideColumns(3, 4); alf.getViewport().hideColumns(0, 1); // getName() can become static in Java 8 ScoreModelI sm = new FeatureDistanceModel(); sm = ScoreModels.getInstance().getScoreModel(sm.getName(), alf.getCurrentView().getAlignPanel()); alf.selectAllSequenceMenuItem_actionPerformed(null); MatrixI dm = sm.findDistances( alf.getViewport().getAlignmentView(true), SimilarityParams.Jalview); assertEquals( dm.getValue(0, 2), 0d, "After hiding last two columns FER1_MESCR (0) should still be identical with RAPSA (2)"); assertEquals( dm.getValue(0, 1), 0d, "After hiding last two columns FER1_MESCR (0) should now also be identical with SPIOL (1)"); for (int s = 0; s < 3; s++) { assertTrue(dm.getValue(s, 3) > 0d, "After hiding last two columns " + alf.getViewport().getAlignment().getSequenceAt(s).getName() + "(" + s + ") should still be distinct from FER1_MAIZE (3)"); } } /** * Check findFeatureAt doesn't return contact features except at contact * points TODO:move to under the FeatureRendererModel test suite */ @Test(groups = { "Functional" }) public void testFindFeatureAt_PointFeature() throws Exception { String alignment = "a CCCCCCGGGGGGCCCCCC\n" + "b CCCCCCGGGGGGCCCCCC\n" + "c CCCCCCGGGGGGCCCCCC\n"; AlignFrame af = new jalview.io.FileLoader(false) .LoadFileWaitTillLoaded(alignment, DataSourceType.PASTE); SequenceI aseq = af.getViewport().getAlignment().getSequenceAt(0); SequenceFeature sf = null; sf = new SequenceFeature("disulphide bond", "", 2, 5, Float.NaN, ""); aseq.addSequenceFeature(sf); assertTrue(sf.isContactFeature()); af.refreshFeatureUI(true); af.getFeatureRenderer().setAllVisible(Arrays.asList("disulphide bond")); Assert.assertEquals(af.getFeatureRenderer().getDisplayedFeatureTypes() .size(), 1, "Should be just one feature type displayed"); // step through and check for pointwise feature presence/absence Assert.assertEquals(af.getFeatureRenderer().findFeaturesAtColumn(aseq, 1) .size(), 0); // step through and check for pointwise feature presence/absence Assert.assertEquals(af.getFeatureRenderer().findFeaturesAtColumn(aseq, 2) .size(), 1); // step through and check for pointwise feature presence/absence Assert.assertEquals(af.getFeatureRenderer().findFeaturesAtColumn(aseq, 3) .size(), 0); // step through and check for pointwise feature presence/absence Assert.assertEquals(af.getFeatureRenderer().findFeaturesAtColumn(aseq, 4) .size(), 0); // step through and check for pointwise feature presence/absence Assert.assertEquals(af.getFeatureRenderer().findFeaturesAtColumn(aseq, 5) .size(), 1); // step through and check for pointwise feature presence/absence Assert.assertEquals(af.getFeatureRenderer().findFeaturesAtColumn(aseq, 6) .size(), 0); } @Test(groups = { "Functional" }) public void testFindDistances() throws Exception { String seqs = ">s1\nABCDE\n>seq2\nABCDE\n"; AlignFrame alf = new FileLoader().LoadFileWaitTillLoaded(seqs, DataSourceType.PASTE); SequenceI s1 = alf.getViewport().getAlignment().getSequenceAt(0); SequenceI s2 = alf.getViewport().getAlignment().getSequenceAt(1); /* * set domain and variant features thus: * ----5 * s1 ddd.. * s1 .vvv. * s1 ..vvv * s2 .ddd. * s2 vv..v * The number of unshared feature types per column is * 20120 (two features of the same type doesn't affect score) * giving an average (pairwise distance) of 5/5 or 1.0 */ s1.addSequenceFeature(new SequenceFeature("domain", null, 1, 3, 0f, null)); s1.addSequenceFeature(new SequenceFeature("variant", null, 2, 4, 0f, null)); s1.addSequenceFeature(new SequenceFeature("variant", null, 3, 5, 0f, null)); s2.addSequenceFeature(new SequenceFeature("domain", null, 2, 4, 0f, null)); s2.addSequenceFeature(new SequenceFeature("variant", null, 1, 2, 0f, null)); s2.addSequenceFeature(new SequenceFeature("variant", null, 5, 5, 0f, null)); alf.setShowSeqFeatures(true); alf.getFeatureRenderer().findAllFeatures(true); ScoreModelI sm = new FeatureDistanceModel(); sm = ScoreModels.getInstance().getScoreModel(sm.getName(), alf.getCurrentView().getAlignPanel()); alf.selectAllSequenceMenuItem_actionPerformed(null); AlignmentView alignmentView = alf.getViewport() .getAlignmentView(true); MatrixI distances = sm.findDistances(alignmentView, SimilarityParams.Jalview); assertEquals(distances.width(), 2); assertEquals(distances.height(), 2); assertEquals(distances.getValue(0, 0), 0d); assertEquals(distances.getValue(1, 1), 0d); assertEquals(distances.getValue(0, 1), 1d, "expected identical pairs. (check normalisation for similarity score)"); assertEquals(distances.getValue(1, 0), 1d); } /** * Verify computed distances with varying parameter options */ @Test(groups = "Functional") public void testFindDistances_withParams() { AlignFrame af = setupAlignmentView(); AlignViewport viewport = af.getViewport(); AlignmentView view = viewport.getAlignmentView(false); ScoreModelI sm = new FeatureDistanceModel(); sm = ScoreModels.getInstance().getScoreModel(sm.getName(), af.alignPanel); /* * feature distance model always normalises by region width * gap-gap is always included (but scores zero) * the only variable parameter is 'includeGaps' */ /* * include gaps * score = 3 + 3 + 0 + 2 + 3 + 2 = 13/6 */ SimilarityParamsI params = new SimilarityParams(true, true, true, true); MatrixI distances = sm.findDistances(view, params); assertEquals(distances.getValue(0, 0), 0d); assertEquals(distances.getValue(1, 1), 0d); assertEquals(distances.getValue(0, 1), 13d / 6); // should be 13d/6 assertEquals(distances.getValue(1, 0), 13d / 6); /* * exclude gaps * score = 3 + 3 + 0 + 0 + 0 + 0 = 6/6 */ params = new SimilarityParams(true, true, false, true); distances = sm.findDistances(view, params); assertEquals(distances.getValue(0, 1), 6d / 6);// should be 6d/6 } /** *
   * Set up
   *   column      1 2 3 4 5 6
   *        seq s1 F R - K - S
   *        seq s2 F S - - L
   *   s1 chain    c c   c   c
   *   s1 domain   d d   d   d
   *   s2 chain    c c     c
   *   s2 metal    m m     m
   *   s2 Pfam     P P     P
   *      scores:  3 3 0 2 3 2
   * 
* * @return */ protected AlignFrame setupAlignmentView() { /* * for now, using space for gap to match callers of * AlignmentView.getSequenceStrings() * may change this to '-' (with corresponding change to matrices) */ SequenceI s1 = new Sequence("s1", "FR K S"); SequenceI s2 = new Sequence("s2", "FS L"); s1.addSequenceFeature(new SequenceFeature("chain", null, 1, 4, 0f, null)); s1.addSequenceFeature(new SequenceFeature("domain", null, 1, 4, 0f, null)); s2.addSequenceFeature(new SequenceFeature("chain", null, 1, 3, 0f, null)); s2.addSequenceFeature(new SequenceFeature("metal", null, 1, 3, 0f, null)); s2.addSequenceFeature(new SequenceFeature("Pfam", null, 1, 3, 0f, null)); AlignmentI al = new Alignment(new SequenceI[] { s1, s2 }); AlignFrame af = new AlignFrame(al, 300, 300); af.setShowSeqFeatures(true); af.getFeatureRenderer().findAllFeatures(true); return af; } }