package jalview.gui; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; import jalview.api.FeatureColourI; import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceI; import jalview.datamodel.features.FeatureMatcher; import jalview.datamodel.features.FeatureMatcherSet; import jalview.datamodel.features.FeatureMatcherSetI; import jalview.io.DataSourceType; import jalview.io.FileLoader; import jalview.schemes.FeatureColour; import jalview.util.matcher.Condition; import java.awt.Color; import java.io.File; import java.io.IOException; import java.util.HashMap; import org.testng.annotations.Test; public class FeatureSettingsTest { /** * Test a roundtrip of save and reload of feature colours and filters as XML * * @throws IOException */ @Test(groups = "Functional") public void testSaveLoad() throws IOException { AlignFrame af = new FileLoader().LoadFileWaitTillLoaded( ">Seq1\nACDEFGHIKLM", DataSourceType.PASTE); SequenceI seq1 = af.getViewport().getAlignment().getSequenceAt(0); /* * add some features to the sequence */ int score = 1; addFeatures(seq1, "type1", score++); addFeatures(seq1, "type2", score++); addFeatures(seq1, "type3", score++); addFeatures(seq1, "type4", score++); addFeatures(seq1, "type5", score++); /* * set colour schemes for features */ FeatureRenderer fr = af.getFeatureRenderer(); // type1: red fr.setColour("type1", new FeatureColour(Color.red)); // type2: by label FeatureColourI byLabel = new FeatureColour(); byLabel.setColourByLabel(true); fr.setColour("type2", byLabel); // type3: by score above threshold FeatureColourI byScore = new FeatureColour(null, Color.BLACK, Color.BLUE, null, 1, 10); byScore.setAboveThreshold(true); byScore.setThreshold(2f); fr.setColour("type3", byScore); // type4: by attribute AF FeatureColourI byAF = new FeatureColour(); byAF.setColourByLabel(true); byAF.setAttributeName("AF"); fr.setColour("type4", byAF); // type5: by attribute CSQ:PolyPhen below threshold FeatureColourI byPolyPhen = new FeatureColour(null, Color.BLACK, Color.BLUE, null, 1, 10); byPolyPhen.setBelowThreshold(true); byPolyPhen.setThreshold(3f); byPolyPhen.setAttributeName("CSQ", "PolyPhen"); fr.setColour("type5", byPolyPhen); /* * set filters for feature types */ // filter type1 features by (label contains "x") FeatureMatcherSetI filterByX = new FeatureMatcherSet(); filterByX.and(FeatureMatcher.byLabel(Condition.Contains, "x")); fr.setFeatureFilter("type1", filterByX); // filter type2 features by (score <= 2.4 and score > 1.1) FeatureMatcherSetI filterByScore = new FeatureMatcherSet(); filterByScore.and(FeatureMatcher.byScore(Condition.LE, "2.4")); filterByScore.and(FeatureMatcher.byScore(Condition.GT, "1.1")); fr.setFeatureFilter("type2", filterByScore); // filter type3 features by (AF contains X OR CSQ:PolyPhen != 0) FeatureMatcherSetI filterByXY = new FeatureMatcherSet(); filterByXY .and(FeatureMatcher.byAttribute(Condition.Contains, "X", "AF")); filterByXY.or(FeatureMatcher.byAttribute(Condition.NE, "0", "CSQ", "PolyPhen")); fr.setFeatureFilter("type3", filterByXY); /* * save colours and filters to an XML file */ File coloursFile = File.createTempFile("testSaveLoad", ".fc"); coloursFile.deleteOnExit(); FeatureSettings fs = new FeatureSettings(af); fs.save(coloursFile); /* * change feature colours and filters */ FeatureColourI pink = new FeatureColour(Color.pink); fr.setColour("type1", pink); fr.setColour("type2", pink); fr.setColour("type3", pink); fr.setColour("type4", pink); fr.setColour("type5", pink); FeatureMatcherSetI filter2 = new FeatureMatcherSet(); filter2.and(FeatureMatcher.byLabel(Condition.NotContains, "y")); fr.setFeatureFilter("type1", filter2); fr.setFeatureFilter("type2", filter2); fr.setFeatureFilter("type3", filter2); fr.setFeatureFilter("type4", filter2); fr.setFeatureFilter("type5", filter2); /* * reload colours and filters from file and verify they are restored */ fs.load(coloursFile); FeatureColourI fc = fr.getFeatureStyle("type1"); assertTrue(fc.isSimpleColour()); assertEquals(fc.getColour(), Color.red); fc = fr.getFeatureStyle("type2"); assertTrue(fc.isColourByLabel()); fc = fr.getFeatureStyle("type3"); assertTrue(fc.isGraduatedColour()); assertNull(fc.getAttributeName()); assertTrue(fc.isAboveThreshold()); assertEquals(fc.getThreshold(), 2f); fc = fr.getFeatureStyle("type4"); assertTrue(fc.isColourByLabel()); assertTrue(fc.isColourByAttribute()); assertEquals(fc.getAttributeName(), new String[] { "AF" }); fc = fr.getFeatureStyle("type5"); assertTrue(fc.isGraduatedColour()); assertTrue(fc.isColourByAttribute()); assertEquals(fc.getAttributeName(), new String[] { "CSQ", "PolyPhen" }); assertTrue(fc.isBelowThreshold()); assertEquals(fc.getThreshold(), 3f); assertEquals(fr.getFeatureFilter("type1").toStableString(), "Label Contains x"); assertEquals(fr.getFeatureFilter("type2").toStableString(), "(Score LE 2.4) AND (Score GT 1.1)"); assertEquals(fr.getFeatureFilter("type3").toStableString(), "(AF Contains X) OR (CSQ:PolyPhen NE 0.0)"); } /** * Adds two features of the given type to the given sequence, also setting the * score as the value of attribute "AF" and sub-attribute "CSQ:PolyPhen" * * @param seq * @param featureType * @param score */ private void addFeatures(SequenceI seq, String featureType, int score) { addFeature(seq, featureType, score++); addFeature(seq, featureType, score); } private void addFeature(SequenceI seq, String featureType, int score) { SequenceFeature sf = new SequenceFeature(featureType, "desc", 1, 2, score, "grp"); sf.setValue("AF", score); sf.setValue("CSQ", new HashMap() { { put("PolyPhen", Integer.toString(score)); } }); seq.addSequenceFeature(sf); } }