2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
23 import static org.testng.AssertJUnit.assertNotNull;
25 import jalview.api.AlignExportSettingI;
26 import jalview.datamodel.Alignment;
27 import jalview.datamodel.AlignmentAnnotation;
28 import jalview.datamodel.AlignmentExportData;
29 import jalview.datamodel.AlignmentI;
30 import jalview.datamodel.Annotation;
31 import jalview.datamodel.HiddenColumns;
32 import jalview.datamodel.Sequence;
33 import jalview.datamodel.SequenceFeature;
34 import jalview.datamodel.SequenceGroup;
35 import jalview.datamodel.SequenceI;
36 import jalview.datamodel.features.SequenceFeatures;
37 import jalview.gui.AlignFrame;
38 import jalview.gui.JvOptionPane;
39 import jalview.json.binding.biojson.v1.ColourSchemeMapper;
40 import jalview.schemes.ColourSchemeI;
41 import jalview.schemes.ResidueColourScheme;
43 import java.awt.event.ActionListener;
44 import java.io.IOException;
45 import java.util.ArrayList;
46 import java.util.HashMap;
47 import java.util.Iterator;
48 import java.util.List;
51 import org.testng.Assert;
52 import org.testng.AssertJUnit;
53 import org.testng.annotations.AfterTest;
54 import org.testng.annotations.BeforeClass;
55 import org.testng.annotations.BeforeMethod;
56 import org.testng.annotations.BeforeTest;
57 import org.testng.annotations.Test;
59 public class JSONFileTest
62 @BeforeClass(alwaysRun = true)
63 public void setUpJvOptionPane()
65 JvOptionPane.setInteractiveMode(false);
66 JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
69 private int TEST_SEQ_HEIGHT = 0;
71 private int TEST_GRP_HEIGHT = 0;
73 private int TEST_ANOT_HEIGHT = 0;
75 private int TEST_CS_HEIGHT = 0;
77 private String TEST_JSON_FILE = "examples/example.json";
79 private Alignment alignment;
81 private HashMap<String, SequenceI> expectedSeqs = new HashMap<>();
83 private HashMap<String, AlignmentAnnotation> expectedAnnots = new HashMap<>();
85 private HashMap<String, SequenceGroup> expectedGrps = new HashMap<>();
87 private HiddenColumns expectedColSel = new HiddenColumns();
89 private SequenceI[] expectedHiddenSeqs = new SequenceI[1];
91 private AlignmentI testAlignment;
93 private int passedCount;
95 private JSONFile testJsonFile;
99 private AlignExportSettingI exportSettings;
101 @BeforeTest(alwaysRun = true)
102 public void setup() throws Exception
105 * construct expected values
106 * nb this have to match the data in examples/example.json
108 // create and add sequences
109 Sequence[] seqs = new Sequence[5];
110 seqs[0] = new Sequence("FER_CAPAN",
111 "SVSATMISTSFMPRKPAVTSL-KPIPNVGE--ALF", 3, 34);
112 seqs[1] = new Sequence("FER1_SOLLC",
113 "SISGTMISTSFLPRKPAVTSL-KAISNVGE--ALF", 3, 34);
114 seqs[2] = new Sequence("Q93XJ9_SOLTU",
115 "SISGTMISTSFLPRKPVVTSL-KAISNVGE--ALF", 3, 34);
116 seqs[3] = new Sequence("FER1_PEA",
117 "ALYGTAVSTSFLRTQPMPMSV-TTTKAFSN--GFL", 6, 37);
118 seqs[4] = new Sequence("Q7XA98_TRIPR",
119 "ALYGTAVSTSFMRRQPVPMSV-ATTTTTKAFPSGF", 6, 39);
121 SequenceI hiddenSeq = new Sequence("FER_TOCH",
122 "FILGTMISKSFLFRKPAVTSL-KAISNVGE--ALF", 3, 34);
123 expectedHiddenSeqs[0] = hiddenSeq;
125 // create and add sequence features
126 SequenceFeature seqFeature2 = new SequenceFeature("feature_x",
127 "theDesc", 6, 15, "Jalview");
128 SequenceFeature seqFeature3 = new SequenceFeature("feature_x",
129 "theDesc", 9, 18, "Jalview");
130 SequenceFeature seqFeature4 = new SequenceFeature("feature_x",
131 "theDesc", 9, 18, "Jalview");
132 // non-positional feature:
133 SequenceFeature seqFeature5 = new SequenceFeature("Domain",
134 "My description", 0, 0, "Pfam");
135 seqs[2].addSequenceFeature(seqFeature2);
136 seqs[3].addSequenceFeature(seqFeature3);
137 seqs[4].addSequenceFeature(seqFeature4);
138 seqs[2].addSequenceFeature(seqFeature5);
140 for (Sequence seq : seqs)
142 seq.createDatasetSequence();
143 expectedSeqs.put(seq.getName(), seq);
146 // create and add a sequence group
147 List<SequenceI> grpSeqs = new ArrayList<>();
148 grpSeqs.add(seqs[1]);
149 grpSeqs.add(seqs[2]);
150 grpSeqs.add(seqs[3]);
151 grpSeqs.add(seqs[4]);
152 SequenceGroup seqGrp = new SequenceGroup(grpSeqs,
154 null, true, true, false, 21, 29);
155 ColourSchemeI scheme = ColourSchemeMapper.getJalviewColourScheme(
157 seqGrp.cs.setColourScheme(scheme);
158 seqGrp.setShowNonconserved(false);
159 seqGrp.setDescription(null);
161 expectedGrps.put(seqGrp.getName(), seqGrp);
163 // create and add annotation
164 Annotation[] annot = new Annotation[35];
165 annot[0] = new Annotation("", "", '\u0000', 0);
166 annot[1] = new Annotation("", "", '\u0000', 0);
167 annot[2] = new Annotation("α", "", 'H', 0);
168 annot[3] = new Annotation("α", "", 'H', 0);
169 annot[4] = new Annotation("α", "", 'H', 0);
170 annot[5] = new Annotation("", "", '\u0000', 0);
171 annot[6] = new Annotation("", "", '\u0000', 0);
172 annot[7] = new Annotation("", "", '\u0000', 0);
173 annot[8] = new Annotation("β", "", 'E', 0);
174 annot[9] = new Annotation("β", "", 'E', 0);
175 annot[10] = new Annotation("β", "", 'E', 0);
176 annot[11] = new Annotation("β", "", 'E', 0);
177 annot[12] = new Annotation("β", "", 'E', 0);
178 annot[13] = new Annotation("β", "", 'E', 0);
179 annot[14] = new Annotation("β", "", 'E', 0);
180 annot[15] = new Annotation("β", "", 'E', 0);
181 annot[16] = new Annotation("", "", '\u0000', 0);
182 annot[17] = new Annotation("", "", '\u0000', 0);
183 annot[18] = new Annotation("", "", '\u0000', 0);
184 annot[19] = new Annotation("", "", '\u0000', 0);
185 annot[20] = new Annotation("", "", '\u0000', 0);
186 annot[21] = new Annotation("", "", '\u0000', 0);
187 annot[22] = new Annotation("", "", '\u0000', 0);
188 annot[23] = new Annotation("", "", '\u0000', 0);
189 annot[24] = new Annotation("", "", '\u0000', 0);
190 annot[25] = new Annotation("", "", '\u0000', 0);
191 annot[26] = new Annotation("α", "", 'H', 0);
192 annot[27] = new Annotation("α", "", 'H', 0);
193 annot[28] = new Annotation("α", "", 'H', 0);
194 annot[29] = new Annotation("α", "", 'H', 0);
195 annot[30] = new Annotation("α", "", 'H', 0);
196 annot[31] = new Annotation("", "", '\u0000', 0);
197 annot[32] = new Annotation("", "", '\u0000', 0);
198 annot[33] = new Annotation("", "", '\u0000', 0);
199 annot[34] = new Annotation("", "", '\u0000', 0);
201 AlignmentAnnotation alignAnnot = new AlignmentAnnotation(
202 "Secondary Structure", "New description", annot);
203 expectedAnnots.put(alignAnnot.label, alignAnnot);
205 expectedColSel.hideColumns(32, 33);
206 expectedColSel.hideColumns(34, 34);
208 TEST_SEQ_HEIGHT = expectedSeqs.size();
209 TEST_GRP_HEIGHT = expectedGrps.size();
210 TEST_ANOT_HEIGHT = expectedAnnots.size();
211 TEST_CS_HEIGHT = expectedColSel.getNumberOfRegions();
213 exportSettings = new AlignExportSettingI()
216 public boolean isExportHiddenSequences()
222 public boolean isExportHiddenColumns()
228 public boolean isExportGroups()
234 public boolean isExportFeatures()
240 public boolean isExportAnnotations()
246 public boolean isCancelled()
252 public AlignmentExportData getAlignExportData()
254 // TODO Auto-generated method stub
259 public void addActionListener(ActionListener actionListener)
261 // TODO Auto-generated method stub
266 public void doShowSettings()
268 // TODO Auto-generated method stub
273 AppletFormatAdapter formatAdapter = new AppletFormatAdapter();
276 alignment = (Alignment) formatAdapter.readFile(TEST_JSON_FILE,
277 DataSourceType.FILE, FileFormat.Json);
278 jf = (JSONFile) formatAdapter.getAlignFile();
280 AlignFrame af = new AlignFrame(alignment, jf.getHiddenSequences(),
281 jf.getHiddenColumns(), AlignFrame.DEFAULT_WIDTH,
282 AlignFrame.DEFAULT_HEIGHT);
283 af.getViewport().setShowSequenceFeatures(jf.isShowSeqFeatures());
284 String colourSchemeName = jf.getGlobalColourScheme();
285 ColourSchemeI cs = ColourSchemeMapper.getJalviewColourScheme(
286 colourSchemeName, alignment);
288 af.getViewport().setFeaturesDisplayed(jf.getDisplayedFeatures());
290 formatAdapter = new AppletFormatAdapter(af.alignPanel, exportSettings);
291 String jsonOutput = formatAdapter.formatSequences(FileFormat.Json,
292 af.alignPanel.getAlignment(), false);
294 formatAdapter = new AppletFormatAdapter();
295 testAlignment = formatAdapter.readFile(jsonOutput,
296 DataSourceType.PASTE, FileFormat.Json);
297 testJsonFile = (JSONFile) formatAdapter.getAlignFile();
298 // System.out.println(jsonOutput);
299 } catch (IOException e)
306 @BeforeMethod(alwaysRun = true)
307 public void methodSetup()
312 @AfterTest(alwaysRun = true)
313 public void tearDown() throws Exception
318 expectedAnnots = null;
320 testAlignment = null;
324 @Test(groups = { "Functional" })
325 public void roundTripTest()
327 assertNotNull("JSON roundtrip test failed!", testJsonFile);
330 @Test(groups = { "Functional" })
331 public void testSeqParsed()
333 assertNotNull("Couldn't read supplied alignment data.", testAlignment);
334 Assert.assertNotNull(testAlignment.getSequences());
335 for (SequenceI seq : testAlignment.getSequences())
337 SequenceI expectedSeq = expectedSeqs.get(seq.getName());
338 AssertJUnit.assertTrue(
339 "Failed Sequence Test for >>> " + seq.getName(),
340 isSeqMatched(expectedSeq, seq));
343 AssertJUnit.assertEquals("Some Sequences did not pass the test",
344 TEST_SEQ_HEIGHT, passedCount);
347 @Test(groups = { "Functional" })
348 public void hiddenColsTest()
350 HiddenColumns cs = testJsonFile.getHiddenColumns();
351 Assert.assertNotNull(cs);
353 Iterator<int[]> it = cs.iterator();
354 Iterator<int[]> colselit = expectedColSel.iterator();
355 Assert.assertTrue(it.hasNext());
356 Assert.assertEquals(cs.getNumberOfRegions(), TEST_CS_HEIGHT);
357 Assert.assertEquals(it.next(), colselit.next(),
358 "Mismatched hidden columns!");
361 @Test(groups = { "Functional" })
362 public void hiddenSeqsTest()
364 Assert.assertNotNull(testJsonFile.getHiddenSequences(),
365 "Hidden sequence Expected but found Null");
366 Assert.assertEquals(jf.getHiddenSequences().length, 1,
370 @Test(groups = { "Functional" })
371 public void colorSchemeTest()
373 Assert.assertNotNull(testJsonFile.getGlobalColourScheme(),
374 "Colourscheme is null, parsing failed!");
375 Assert.assertEquals(testJsonFile.getGlobalColourScheme(), "Zappo",
376 "Zappo colour scheme expected!");
380 * Test for bug JAL-2489, NPE when exporting BioJSON with global colour
381 * scheme, and a group colour scheme, set as 'None'
383 @Test(groups = { "Functional" })
384 public void testBioJSONRoundTripWithColourSchemeNone()
386 AppletFormatAdapter formatAdapter = new AppletFormatAdapter();
388 Alignment _alignment;
391 // load example BioJSON file
392 _alignment = (Alignment) formatAdapter.readFile(TEST_JSON_FILE,
393 DataSourceType.FILE, FileFormat.Json);
394 JSONFile bioJsonFile = (JSONFile) formatAdapter.getAlignFile();
395 AlignFrame alignFrame = new AlignFrame(_alignment,
396 bioJsonFile.getHiddenSequences(),
397 bioJsonFile.getHiddenColumns(), AlignFrame.DEFAULT_WIDTH,
398 AlignFrame.DEFAULT_HEIGHT);
401 * Create a group on the alignment;
402 * Change global and group colour scheme to 'None' and perform round trip
404 SequenceGroup sg = new SequenceGroup();
405 sg.addSequence(_alignment.getSequenceAt(0), false);
406 sg.setColourScheme(null);
407 ColourSchemeI cs = ColourSchemeMapper.getJalviewColourScheme(
408 ResidueColourScheme.NONE, _alignment);
409 alignFrame.changeColour(cs);
410 alignFrame.getViewport().setFeaturesDisplayed(
411 bioJsonFile.getDisplayedFeatures());
412 formatAdapter = new AppletFormatAdapter(alignFrame.alignPanel,
414 // export BioJSON string
415 String jsonOutput = formatAdapter.formatSequences(FileFormat.Json,
416 alignFrame.alignPanel.getAlignment(), false);
417 // read back Alignment from BioJSON string
418 formatAdapter = new AppletFormatAdapter();
419 formatAdapter.readFile(jsonOutput, DataSourceType.PASTE,
421 // assert 'None' colour scheme is retained after round trip
422 JSONFile _bioJsonFile = (JSONFile) formatAdapter.getAlignFile();
423 Assert.assertEquals(_bioJsonFile.getGlobalColourScheme(),
424 ResidueColourScheme.NONE);
425 } catch (IOException e)
431 @Test(groups = { "Functional" })
432 public void isShowSeqFeaturesSet()
434 Assert.assertTrue(testJsonFile.isShowSeqFeatures(),
435 "Sequence feature isDisplayed setting expected to be true");
438 @Test(groups = { "Functional" })
439 public void testGrpParsed()
441 Assert.assertNotNull(testAlignment.getGroups());
442 for (SequenceGroup seqGrp : testAlignment.getGroups())
444 SequenceGroup expectedGrp = expectedGrps.get(seqGrp.getName());
445 AssertJUnit.assertTrue(
446 "Failed SequenceGroup Test for >>> " + seqGrp.getName(),
447 isGroupMatched(expectedGrp, seqGrp));
450 AssertJUnit.assertEquals("Some SequenceGroups did not pass the test",
451 TEST_GRP_HEIGHT, passedCount);
454 @Test(groups = { "Functional" })
455 public void testAnnotationParsed()
457 Assert.assertNotNull(testAlignment.getAlignmentAnnotation());
458 for (AlignmentAnnotation annot : testAlignment.getAlignmentAnnotation())
460 AlignmentAnnotation expectedAnnot = expectedAnnots.get(annot.label);
461 AssertJUnit.assertTrue("Failed AlignmentAnnotation Test for >>> "
462 + annot.label, isAnnotationMatched(expectedAnnot, annot));
465 AssertJUnit.assertEquals("Some Sequences did not pass the test",
466 TEST_ANOT_HEIGHT, passedCount);
469 public boolean isAnnotationMatched(AlignmentAnnotation eAnnot,
470 AlignmentAnnotation annot)
472 if (!eAnnot.label.equals(annot.label)
473 || !eAnnot.description.equals(annot.description)
474 || eAnnot.annotations.length != annot.annotations.length)
479 for (int x = 0; x < annot.annotations.length; x++)
481 Annotation y = annot.annotations[x];
482 Annotation z = annot.annotations[x];
484 if (!y.displayCharacter.equals(z.displayCharacter)
485 || y.value != z.value
486 || y.secondaryStructure != z.secondaryStructure)
494 boolean isSeqMatched(SequenceI expectedSeq, SequenceI actualSeq)
496 System.out.println("Testing >>> " + actualSeq.getName());
498 if (expectedSeq.getName().equals(actualSeq.getName())
499 && expectedSeq.getSequenceAsString().equals(
500 actualSeq.getSequenceAsString())
501 && expectedSeq.getStart() == actualSeq.getStart()
502 && expectedSeq.getEnd() == actualSeq.getEnd()
503 && featuresMatched(expectedSeq, actualSeq))
510 public boolean isGroupMatched(SequenceGroup expectedGrp,
511 SequenceGroup actualGrp)
514 System.out.println("Testing >>> " + actualGrp.getName());
515 System.out.println(expectedGrp.getName() + " | " + actualGrp.getName());
516 System.out.println(expectedGrp.getColourText() + " | "
517 + actualGrp.getColourText());
518 System.out.println(expectedGrp.getDisplayBoxes() + " | "
519 + actualGrp.getDisplayBoxes());
520 System.out.println(expectedGrp.getIgnoreGapsConsensus() + " | "
521 + actualGrp.getIgnoreGapsConsensus());
522 System.out.println(expectedGrp.getSequences().size() + " | "
523 + actualGrp.getSequences().size());
524 System.out.println(expectedGrp.getStartRes() + " | "
525 + actualGrp.getStartRes());
526 System.out.println(expectedGrp.getEndRes() + " | "
527 + actualGrp.getEndRes());
528 System.out.println(expectedGrp.cs.getColourScheme() + " | "
529 + actualGrp.cs.getColourScheme());
531 boolean colourSchemeMatches = (expectedGrp.cs.getColourScheme() == null && actualGrp.cs
532 .getColourScheme() == null)
533 || expectedGrp.cs.getColourScheme().getClass()
534 .equals(actualGrp.cs.getColourScheme().getClass());
535 if (expectedGrp.getName().equals(actualGrp.getName())
536 && expectedGrp.getColourText() == actualGrp.getColourText()
537 && expectedGrp.getDisplayBoxes() == actualGrp.getDisplayBoxes()
538 && expectedGrp.getIgnoreGapsConsensus() == actualGrp
539 .getIgnoreGapsConsensus()
540 && colourSchemeMatches
541 && expectedGrp.getSequences().size() == actualGrp
542 .getSequences().size()
543 && expectedGrp.getStartRes() == actualGrp.getStartRes()
544 && expectedGrp.getEndRes() == actualGrp.getEndRes())
551 private boolean featuresMatched(SequenceI seq1, SequenceI seq2)
555 if (seq1 == null && seq2 == null)
560 List<SequenceFeature> inFeature = seq1.getFeatures().getAllFeatures();
561 List<SequenceFeature> outFeature = seq2.getFeatures()
564 if (inFeature.size() != outFeature.size())
566 System.err.println("Feature count in: " + inFeature.size()
567 + ", out: " + outFeature.size());
571 SequenceFeatures.sortFeatures(inFeature, true);
572 SequenceFeatures.sortFeatures(outFeature, true);
574 for (SequenceFeature in : inFeature)
576 SequenceFeature out = outFeature.get(i);
578 System.out.println(out.getType() + " | " + in.getType());
579 System.out.println(out.getBegin() + " | " + in.getBegin());
580 System.out.println(out.getEnd() + " | " + in.getEnd());
584 System.err.println("Mismatch of " + in.toString() + " "
589 if (in.getBegin() == out.getBegin() && in.getEnd() == out.getEnd()
590 && in.getScore() == out.getScore()
591 && in.getFeatureGroup().equals(out.getFeatureGroup())
592 && in.getType().equals(out.getType())
593 && mapsMatch(in.otherDetails, out.otherDetails))
598 System.err.println("Feature[" + i + "] mismatch, in: "
599 + in.toString() + ", out: "
600 + outFeature.get(i).toString());
606 } catch (Exception e)
610 // System.out.println(">>>>>>>>>>>>>> features matched : " + matched);
614 boolean mapsMatch(Map<String, Object> m1, Map<String, Object> m2)
616 if (m1 == null || m2 == null)
618 if (m1 != null || m2 != null)
621 .println("only one SequenceFeature.otherDetails is not null");
629 if (m1.size() != m2.size())
631 System.err.println("otherDetails map different sizes");
634 for (String key : m1.keySet())
636 if (!m2.containsKey(key))
638 System.err.println(key + " in only one otherDetails");
641 if (m1.get(key) == null && m2.get(key) != null || m1.get(key) != null
642 && m2.get(key) == null || !m1.get(key).equals(m2.get(key)))
644 System.err.println(key + " values in otherDetails don't match");
652 * Test group roundtrip with null (None) group colour scheme
654 * @throws IOException
656 @Test(groups = { "Functional" })
657 public void testGrpParsed_colourNone() throws IOException
659 AlignmentI copy = new Alignment(testAlignment);
660 SequenceGroup sg = testAlignment.getGroups().get(0);
661 SequenceGroup copySg = new SequenceGroup(new ArrayList<SequenceI>(),
663 null, sg.getDisplayBoxes(), sg.getDisplayText(),
664 sg.getColourText(), sg.getStartRes(), sg.getEndRes());
665 for (SequenceI seq : sg.getSequences())
667 int seqIndex = testAlignment.findIndex(seq);
668 copySg.addSequence(copy.getSequenceAt(seqIndex), false);
670 copy.addGroup(copySg);
672 AlignFrame af = new AlignFrame(copy, copy.getWidth(), copy.getHeight());
673 AppletFormatAdapter formatAdapter = new AppletFormatAdapter(
675 String jsonOutput = formatAdapter.formatSequences(FileFormat.Json,
677 formatAdapter = new AppletFormatAdapter();
678 AlignmentI newAlignment = formatAdapter.readFile(jsonOutput,
679 DataSourceType.PASTE, FileFormat.Json);
681 Assert.assertNotNull(newAlignment.getGroups());
682 for (SequenceGroup seqGrp : newAlignment.getGroups())
684 SequenceGroup expectedGrp = copySg;
685 AssertJUnit.assertTrue(
686 "Failed SequenceGroup Test for >>> " + seqGrp.getName(),
687 isGroupMatched(expectedGrp, seqGrp));
690 AssertJUnit.assertEquals("Some SequenceGroups did not pass the test",
691 TEST_GRP_HEIGHT, passedCount);