From: gmungoc Date: Tue, 29 Nov 2016 14:20:41 +0000 (+0000) Subject: Merge branch 'develop' into features/JAL-2295setChimeraAttributes X-Git-Tag: Release_2_11_0~62^2~41 X-Git-Url: http://source.jalview.org/gitweb/?a=commitdiff_plain;h=5965127c38ff1a35d10d806c4b4537cdc1e39579;p=jalview.git Merge branch 'develop' into features/JAL-2295setChimeraAttributes Conflicts: test/jalview/ext/rbvi/chimera/JalviewChimeraView.java --- 5965127c38ff1a35d10d806c4b4537cdc1e39579 diff --cc src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java index cc1de6a,b009948..1ff0466 --- a/src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java +++ b/src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java @@@ -27,11 -27,9 +27,12 @@@ import jalview.bin.Cache import jalview.datamodel.AlignmentI; import jalview.datamodel.ColumnSelection; import jalview.datamodel.PDBEntry; +import jalview.datamodel.SearchResultMatchI; +import jalview.datamodel.SearchResults; +import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceI; import jalview.httpserver.AbstractRequestHandler; + import jalview.io.DataSourceType; import jalview.schemes.ColourSchemeI; import jalview.schemes.ResidueProperties; import jalview.structure.AtomSpec; diff --cc src/jalview/gui/ChimeraViewFrame.java index e76f11e,b82eef3..4c38898 --- a/src/jalview/gui/ChimeraViewFrame.java +++ b/src/jalview/gui/ChimeraViewFrame.java @@@ -26,10 -26,9 +26,10 @@@ import jalview.datamodel.AlignmentI import jalview.datamodel.ColumnSelection; import jalview.datamodel.PDBEntry; import jalview.datamodel.SequenceI; +import jalview.ext.rbvi.chimera.ChimeraCommands; import jalview.ext.rbvi.chimera.JalviewChimeraBinding; import jalview.gui.StructureViewer.ViewerType; - import jalview.io.AppletFormatAdapter; + import jalview.io.DataSourceType; import jalview.io.JalviewFileChooser; import jalview.io.JalviewFileView; import jalview.io.StructureFile; diff --cc test/jalview/ext/jmol/JmolViewerTest.java index 3a4e9bf,959ecab..995b099 --- a/test/jalview/ext/jmol/JmolViewerTest.java +++ b/test/jalview/ext/jmol/JmolViewerTest.java @@@ -24,9 -24,9 +24,10 @@@ import static org.testng.AssertJUnit.as import jalview.api.structures.JalviewStructureDisplayI; import jalview.bin.Cache; +import jalview.bin.Jalview; import jalview.datamodel.SequenceI; import jalview.gui.AlignFrame; + import jalview.gui.JvOptionPane; import jalview.gui.Preferences; import jalview.gui.StructureViewer; import jalview.gui.StructureViewer.ViewerType; diff --cc test/jalview/ext/rbvi/chimera/ChimeraCommandsTest.java index f24ff22,d0ea751..70c6922 --- a/test/jalview/ext/rbvi/chimera/ChimeraCommandsTest.java +++ b/test/jalview/ext/rbvi/chimera/ChimeraCommandsTest.java @@@ -20,11 -20,13 +20,13 @@@ */ package jalview.ext.rbvi.chimera; -import static org.testng.AssertJUnit.assertEquals; -import static org.testng.AssertJUnit.assertTrue; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + import jalview.gui.JvOptionPane; + import java.awt.Color; -import java.util.Arrays; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@@ -33,7 -36,63 +36,15 @@@ import org.testng.annotations.Test public class ChimeraCommandsTest { + + @BeforeClass(alwaysRun = true) + public void setUpJvOptionPane() + { + JvOptionPane.setInteractiveMode(false); + JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION); + } + @Test(groups = { "Functional" }) - public void testAddColourRange() - { - Map>>> map = new LinkedHashMap>>>(); - ChimeraCommands.addColourRange(map, Color.pink, 1, 2, 4, "A"); - ChimeraCommands.addColourRange(map, Color.pink, 1, 8, 8, "A"); - ChimeraCommands.addColourRange(map, Color.pink, 1, 5, 7, "B"); - ChimeraCommands.addColourRange(map, Color.red, 1, 3, 5, "A"); - ChimeraCommands.addColourRange(map, Color.red, 0, 1, 4, "B"); - ChimeraCommands.addColourRange(map, Color.orange, 0, 5, 9, "C"); - - // three colours mapped - assertEquals(3, map.keySet().size()); - - // Red has two models, Pink and Orange one each - assertEquals(2, map.get(Color.red).keySet().size()); - assertEquals(1, map.get(Color.orange).keySet().size()); - assertEquals(1, map.get(Color.pink).keySet().size()); - - // pink model 1 has two chains, red.0 / red.1 / orange.0 one each - assertEquals(2, map.get(Color.pink).get(1).keySet().size()); - assertEquals(1, map.get(Color.red).get(0).keySet().size()); - assertEquals(1, map.get(Color.red).get(1).keySet().size()); - assertEquals(1, map.get(Color.orange).get(0).keySet().size()); - - // inspect positions - List posList = map.get(Color.pink).get(1).get("A"); - assertEquals(2, posList.size()); - assertTrue(Arrays.equals(new int[] { 2, 4 }, posList.get(0))); - assertTrue(Arrays.equals(new int[] { 8, 8 }, posList.get(1))); - - posList = map.get(Color.pink).get(1).get("B"); - assertEquals(1, posList.size()); - assertTrue(Arrays.equals(new int[] { 5, 7 }, posList.get(0))); - - posList = map.get(Color.red).get(0).get("B"); - assertEquals(1, posList.size()); - assertTrue(Arrays.equals(new int[] { 1, 4 }, posList.get(0))); - - posList = map.get(Color.red).get(1).get("A"); - assertEquals(1, posList.size()); - assertTrue(Arrays.equals(new int[] { 3, 5 }, posList.get(0))); - - posList = map.get(Color.orange).get(0).get("C"); - assertEquals(1, posList.size()); - assertTrue(Arrays.equals(new int[] { 5, 9 }, posList.get(0))); - } - - @Test(groups = { "Functional" }) public void testBuildColourCommands() { diff --cc test/jalview/ext/rbvi/chimera/JalviewChimeraView.java index 449b219,f4fb40b..d85bb10 --- a/test/jalview/ext/rbvi/chimera/JalviewChimeraView.java +++ b/test/jalview/ext/rbvi/chimera/JalviewChimeraView.java @@@ -20,39 -20,20 +20,40 @@@ */ package jalview.ext.rbvi.chimera; -import static org.testng.AssertJUnit.assertEquals; -import static org.testng.AssertJUnit.assertTrue; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; +import jalview.api.FeatureRenderer; import jalview.api.structures.JalviewStructureDisplayI; import jalview.bin.Cache; +import jalview.bin.Jalview; +import jalview.datamodel.DBRefEntry; +import jalview.datamodel.PDBEntry; +import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceI; import jalview.gui.AlignFrame; +import jalview.gui.Desktop; + import jalview.gui.JvOptionPane; import jalview.gui.Preferences; import jalview.gui.StructureViewer; import jalview.gui.StructureViewer.ViewerType; +import jalview.io.FileLoader; - import jalview.io.FormatAdapter; +import jalview.structure.StructureMapping; +import jalview.structure.StructureSelectionManager; +import jalview.ws.sifts.SiftsClient; +import jalview.ws.sifts.SiftsException; +import jalview.ws.sifts.SiftsSettings; + +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.Vector; + import jalview.io.DataSourceType; import org.testng.annotations.AfterClass; +import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @@@ -60,8 -41,13 +61,15 @@@ public class JalviewChimeraView { + @BeforeClass(alwaysRun = true) + public void setUpJvOptionPane() + { + JvOptionPane.setInteractiveMode(false); + JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION); + } + + private JalviewStructureDisplayI chimeraViewer; + /** * @throws java.lang.Exception */ @@@ -87,388 -65,57 +95,388 @@@ @AfterClass(alwaysRun = true) public static void tearDownAfterClass() throws Exception { - jalview.gui.Desktop.instance.closeAll_actionPerformed(null); + Desktop.instance.closeAll_actionPerformed(null); + } + + @AfterMethod(alwaysRun = true) + public void tearDownAfterTest() throws Exception + { + SiftsClient.setMockSiftsFile(null); + if (chimeraViewer != null) + { + chimeraViewer.closeViewer(true); + } } - @Test(groups = { "Functional" }) + /** + * Load 1GAQ and view the first structure for which a PDB id is found. Note no + * network connection is needed - PDB file is read locally, SIFTS fetch fails + * so mapping falls back to Needleman-Wunsch - ok for this test. + */ + // External as local install of Chimera required + @Test(groups = { "External" }) public void testSingleSeqViewChimera() { - Cache.setProperty(Preferences.STRUCTURE_DISPLAY, - ViewerType.CHIMERA.name()); String inFile = "examples/1gaq.txt"; - AlignFrame af = new jalview.io.FileLoader().LoadFileWaitTillLoaded( - inFile, DataSourceType.FILE); - assertTrue("Didn't read input file " + inFile, af != null); - for (SequenceI sq : af.getViewport().getAlignment().getSequences()) + AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(inFile, - FormatAdapter.FILE); ++ DataSourceType.FILE); + assertNotNull(af, "Failed to create AlignFrame"); + SequenceI sq = af.getViewport().getAlignment().getSequenceAt(0); + assertEquals(sq.getName(), "1GAQ|A"); + SequenceI dsq = sq.getDatasetSequence(); + Vector pdbIds = dsq.getAllPDBEntries(); + assertEquals(pdbIds.size(), 1); + PDBEntry pdbEntry = pdbIds.get(0); + assertEquals(pdbEntry.getId(), "1GAQ"); + StructureViewer structureViewer = new StructureViewer(af.getViewport() + .getStructureSelectionManager()); + chimeraViewer = structureViewer.viewStructures(pdbEntry, + new SequenceI[] { sq }, af.getCurrentView().getAlignPanel()); + JalviewChimeraBinding binding = (JalviewChimeraBinding) chimeraViewer + .getBinding(); + + /* + * Wait for viewer load thread to complete + */ + while (!binding.isFinishedInit()) { - System.out.println("** sq=" + sq.getName()); - SequenceI dsq = sq.getDatasetSequence(); - while (dsq.getDatasetSequence() != null) + try + { + Thread.sleep(500); + } catch (InterruptedException e) { - dsq = dsq.getDatasetSequence(); } - if (dsq.getAllPDBEntries() != null - && dsq.getAllPDBEntries().size() > 0) + } + + assertTrue(binding.isChimeraRunning(), "Failed to start Chimera"); + + assertEquals(chimeraViewer.getBinding().getPdbCount(), 1); + chimeraViewer.closeViewer(true); + chimeraViewer = null; + return; + } + + /** + * Test for writing Jalview features as attributes on mapped residues in + * Chimera. Note this uses local copies of PDB and SIFTS file, no network + * connection required. + * + * @throws IOException + * @throws SiftsException + */ + // External as this requires a local install of Chimera + @Test(groups = { "External" }) + public void testTransferFeatures() throws IOException, SiftsException + { + String inFile = "examples/uniref50.fa"; + AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(inFile, - FormatAdapter.FILE); ++ DataSourceType.FILE); + assertNotNull(af, "Failed to create AlignFrame"); + SequenceI sq = af.getViewport().getAlignment().findName("FER2_ARATH"); + assertNotNull(sq, "Didn't find FER2_ARATH"); + + /* + * need a Uniprot dbref for SIFTS mapping to work!! + */ + sq.addDBRef(new DBRefEntry("UNIPROT", "0", "P16972", null)); + + /* + * use local test PDB and SIFTS files + */ + String pdbFilePath = new File( + "test/jalview/ext/rbvi/chimera/4zho.pdb").getPath(); + PDBEntry pdbEntry = new PDBEntry("4ZHO", null, null, pdbFilePath); + String siftsFilePath = new File( + "test/jalview/ext/rbvi/chimera/4zho.xml.gz") + .getPath(); + SiftsClient.setMockSiftsFile(new File(siftsFilePath)); + + StructureViewer structureViewer = new StructureViewer(af.getViewport() + .getStructureSelectionManager()); + chimeraViewer = structureViewer.viewStructures(pdbEntry, + new SequenceI[] { sq }, af.getCurrentView().getAlignPanel()); + + JalviewChimeraBinding binding = (JalviewChimeraBinding) chimeraViewer + .getBinding(); + do + { + try + { + Thread.sleep(500); + } catch (InterruptedException e) + { + } + } while (!binding.isFinishedInit()); + + assertTrue(binding.isChimeraRunning(), "Failed to launch Chimera"); + + assertEquals(binding.getPdbCount(), 1); + + /* + * check mapping is (sequence) 53-145 to (structure) 2-94 A/B + * (or possibly 52-145 to 1-94 - see JAL-2319) + */ + StructureSelectionManager ssm = binding.getSsm(); + String pdbFile = binding.getPdbFile()[0]; + StructureMapping[] mappings = ssm.getMapping(pdbFile); + assertTrue(mappings[0].getMappingDetailsOutput().contains("SIFTS"), + "Failed to perform SIFTS mapping"); + assertEquals(mappings.length, 2); + assertEquals(mappings[0].getChain(), "A"); + assertEquals(mappings[0].getPDBResNum(53), 2); + assertEquals(mappings[0].getPDBResNum(145), 94); + assertEquals(mappings[1].getChain(), "B"); + assertEquals(mappings[1].getPDBResNum(53), 2); + assertEquals(mappings[1].getPDBResNum(145), 94); + + /* + * now add some features to FER2_ARATH + */ + // feature on a sequence region not mapped to structure: + sq.addSequenceFeature(new SequenceFeature("transit peptide", + "chloroplast", 1, 51, Float.NaN, null)); + // feature on a region mapped to structure: + sq.addSequenceFeature(new SequenceFeature("domain", + "2Fe-2S ferredoxin-type", 55, 145, Float.NaN, null)); + // on sparse positions of the sequence + sq.addSequenceFeature(new SequenceFeature("metal ion-binding site", + "Iron-Sulfur (2Fe-2S)", 91, 91, Float.NaN, null)); + sq.addSequenceFeature(new SequenceFeature("metal ion-binding site", + "Iron-Sulfur (2Fe-2S)", 96, 96, Float.NaN, null)); + // on a sequence region that is partially mapped to structure: + sq.addSequenceFeature(new SequenceFeature("helix", null, 50, 60, + Float.NaN, null)); + // and again: + sq.addSequenceFeature(new SequenceFeature("chain", null, 50, 70, + Float.NaN, null)); + // add numeric valued features - score is set as attribute value + sq.addSequenceFeature(new SequenceFeature("kd", "hydrophobicity", 62, + 62, -2.1f, null)); + sq.addSequenceFeature(new SequenceFeature("kd", "hydrophobicity", 65, + 65, 3.6f, null)); + sq.addSequenceFeature(new SequenceFeature("RESNUM", "ALA: 2 4zhoA", + 53, 53, Float.NaN, null)); + + /* + * set all features visible except for chain + */ + af.setShowSeqFeatures(true); + FeatureRenderer fr = af.getFeatureRenderer(); + fr.setVisible("transit peptide"); + fr.setVisible("domain"); + fr.setVisible("metal ion-binding site"); + fr.setVisible("helix"); + fr.setVisible("kd"); + fr.setVisible("RESNUM"); + + /* + * 'perform' menu action to copy visible features to + * attributes in Chimera + */ + // TODO rename and pull up method to binding interface + // once functionality is added for Jmol as well + binding.sendFeaturesToViewer(af.getViewport().getAlignPanel()); + + /* + * give Chimera time to open the commands file and execute it + */ + try + { + Thread.sleep(1000); + } catch (InterruptedException e) + { + } + + /* + * ask Chimera for its residue attribute names + */ + List reply = binding.sendChimeraCommand("list resattr", true); + // prefixed and sanitised attribute names for Jalview features: + assertTrue(reply.contains("resattr jv_domain")); + assertTrue(reply.contains("resattr jv_metal_ion_binding_site")); + assertTrue(reply.contains("resattr jv_helix")); + assertTrue(reply.contains("resattr jv_kd")); + assertTrue(reply.contains("resattr jv_RESNUM")); + // feature is not on a mapped region - no attribute created + assertFalse(reply.contains("resattr jv_transit_peptide")); + // feature is not visible - no attribute created + assertFalse(reply.contains("resattr jv_chain")); + + /* + * ask Chimera for residues with an attribute + * 91 and 96 on sequence --> residues 40 and 45 on chains A and B + */ + reply = binding.sendChimeraCommand( + "list resi att jv_metal_ion_binding_site", true); + assertEquals(reply.size(), 4); + assertTrue(reply + .contains("residue id #0:40.A jv_metal_ion_binding_site \"Iron-Sulfur (2Fe-2S)\" index 40")); + assertTrue(reply + .contains("residue id #0:45.A jv_metal_ion_binding_site \"Iron-Sulfur (2Fe-2S)\" index 45")); + assertTrue(reply + .contains("residue id #0:40.B jv_metal_ion_binding_site \"Iron-Sulfur (2Fe-2S)\" index 40")); + assertTrue(reply + .contains("residue id #0:45.B jv_metal_ion_binding_site \"Iron-Sulfur (2Fe-2S)\" index 45")); + + /* + * check attributes with score values + * sequence positions 62 and 65 --> residues 11 and 14 on chains A and B + */ + reply = binding.sendChimeraCommand("list resi att jv_kd", true); + assertEquals(reply.size(), 4); + assertTrue(reply.contains("residue id #0:11.A jv_kd -2.1 index 11")); + assertTrue(reply.contains("residue id #0:14.A jv_kd 3.6 index 14")); + assertTrue(reply.contains("residue id #0:11.B jv_kd -2.1 index 11")); + assertTrue(reply.contains("residue id #0:14.B jv_kd 3.6 index 14")); + + /* + * list residues with positive kd score + */ + reply = binding.sendChimeraCommand( + "list resi spec :*/jv_kd>0 attr jv_kd", true); + assertEquals(reply.size(), 2); + assertTrue(reply.contains("residue id #0:14.A jv_kd 3.6 index 14")); + assertTrue(reply.contains("residue id #0:14.B jv_kd 3.6 index 14")); + + SiftsClient.setMockSiftsFile(null); + chimeraViewer.closeViewer(true); + chimeraViewer = null; + } + + /** + * Test for creating Jalview features from attributes on mapped residues in + * Chimera. Note this uses local copies of PDB and SIFTS file, no network + * connection required. + * + * @throws IOException + * @throws SiftsException + */ + // External as this requires a local install of Chimera + @Test(groups = { "External" }) + public void testGetAttributes() throws IOException, SiftsException + { + String inFile = "examples/uniref50.fa"; + AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(inFile, - FormatAdapter.FILE); ++ DataSourceType.FILE); + assertNotNull(af, "Failed to create AlignFrame"); + SequenceI fer2Arath = af.getViewport().getAlignment() + .findName("FER2_ARATH"); + assertNotNull(fer2Arath, "Didn't find FER2_ARATH"); + + /* + * need a Uniprot dbref for SIFTS mapping to work!! + */ + fer2Arath.addDBRef(new DBRefEntry("UNIPROT", "0", "P16972", null)); + + /* + * use local test PDB and SIFTS files + */ + String pdbFilePath = new File( + "test/jalview/ext/rbvi/chimera/4zho.pdb").getPath(); + PDBEntry pdbEntry = new PDBEntry("4ZHO", null, null, pdbFilePath); + String siftsFilePath = new File( + "test/jalview/ext/rbvi/chimera/4zho.xml.gz") + .getPath(); + SiftsClient.setMockSiftsFile(new File(siftsFilePath)); + + StructureViewer structureViewer = new StructureViewer(af.getViewport() + .getStructureSelectionManager()); + chimeraViewer = structureViewer.viewStructures(pdbEntry, + new SequenceI[] { fer2Arath }, af.getCurrentView() + .getAlignPanel()); + + JalviewChimeraBinding binding = (JalviewChimeraBinding) chimeraViewer + .getBinding(); + do + { + try + { + Thread.sleep(500); + } catch (InterruptedException e) { - for (int q = 0; q < dsq.getAllPDBEntries().size(); q++) - { - final StructureViewer structureViewer = new StructureViewer(af - .getViewport().getStructureSelectionManager()); - structureViewer.setViewerType(ViewerType.CHIMERA); - JalviewStructureDisplayI chimeraViewer = structureViewer - .viewStructures(dsq.getAllPDBEntries().elementAt(q), - new SequenceI[] { sq }, af.getCurrentView() - .getAlignPanel()); - /* - * Wait for viewer load thread to complete - */ - while (!chimeraViewer.getBinding().isFinishedInit()) - { - try - { - Thread.sleep(500); - } catch (InterruptedException e) - { - } - } - assertEquals(1, chimeraViewer.getBinding().getPdbCount()); - chimeraViewer.closeViewer(true); - // todo: break here means only once through this loop? - break; - } - break; } + } while (!binding.isFinishedInit()); + + assertTrue(binding.isChimeraRunning(), "Failed to launch Chimera"); + + assertEquals(binding.getPdbCount(), 1); + + /* + * 'perform' menu action to copy visible features to + * attributes in Chimera + */ + // TODO rename and pull up method to binding interface + // once functionality is added for Jmol as well + binding.copyStructureAttributesToFeatures("isHelix", af.getViewport() + .getAlignPanel()); + + /* + * verify 22 residues have isHelix feature + * (may merge into ranges in future) + */ + af.setShowSeqFeatures(true); + FeatureRenderer fr = af.getFeatureRenderer(); + fr.setVisible("isHelix"); + for (int res = 75; res <= 83; res++) + { + checkFeaturesAtRes(fer2Arath, fr, res, "isHelix"); } + for (int res = 117; res <= 123; res++) + { + checkFeaturesAtRes(fer2Arath, fr, res, "isHelix"); + } + for (int res = 129; res <= 131; res++) + { + checkFeaturesAtRes(fer2Arath, fr, res, "isHelix"); + } + for (int res = 143; res <= 145; res++) + { + checkFeaturesAtRes(fer2Arath, fr, res, "isHelix"); + } + + /* + * fetch a numeric valued attribute + */ + binding.copyStructureAttributesToFeatures("phi", af.getViewport() + .getAlignPanel()); + fr.setVisible("phi"); + List fs = fr.findFeaturesAtRes(fer2Arath, 54); + assertEquals(fs.size(), 3); + assertEquals(fs.get(0).getType(), "RESNUM"); + assertEquals(fs.get(1).getType(), "phi"); + assertEquals(fs.get(2).getType(), "phi"); + assertEquals(fs.get(1).getDescription(), "A"); // chain + assertEquals(fs.get(2).getDescription(), "B"); + assertEquals(fs.get(1).getScore(), -131.0713f, 0.001f); + assertEquals(fs.get(2).getScore(), -127.39512, 0.001f); + + /* + * tear down - also in AfterMethod + */ + SiftsClient.setMockSiftsFile(null); + chimeraViewer.closeViewer(true); + chimeraViewer = null; + } + + /** + * Helper method to verify new feature at a sequence position + * + * @param seq + * @param fr + * @param res + * @param featureType + */ + protected void checkFeaturesAtRes(SequenceI seq, FeatureRenderer fr, + int res, String featureType) + { + String where = "at position " + res; + List fs = fr.findFeaturesAtRes(seq, res); + assertEquals(fs.size(), 2, where); + assertEquals(fs.get(0).getType(), "RESNUM", where); + SequenceFeature sf = fs.get(1); + assertEquals(sf.getType(), featureType, where); + assertEquals(sf.getFeatureGroup(), "Chimera", where); + assertEquals(sf.getDescription(), "True", where); + assertEquals(sf.getScore(), Float.NaN, where); } }