JAL-629 Test and fix --annotation --ssannotation args. Added a viewerType arg/subval...
[jalview.git] / test / jalview / gui / StructureChooserTest.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
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.
11  *  
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.
16  * 
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.
20  */
21 package jalview.gui;
22
23 import static org.testng.Assert.assertEquals;
24 import static org.testng.AssertJUnit.assertNotNull;
25 import static org.testng.AssertJUnit.assertTrue;
26
27 import java.io.File;
28 import java.util.Collection;
29 import java.util.List;
30 import java.util.Vector;
31
32 import org.junit.Assert;
33 import org.testng.annotations.AfterMethod;
34 import org.testng.annotations.BeforeClass;
35 import org.testng.annotations.BeforeMethod;
36 import org.testng.annotations.DataProvider;
37 import org.testng.annotations.Test;
38
39 import jalview.api.AlignViewportI;
40 import jalview.bin.Cache;
41 import jalview.bin.Jalview;
42 import jalview.datamodel.AlignmentAnnotation;
43 import jalview.datamodel.AlignmentI;
44 import jalview.datamodel.DBRefEntry;
45 import jalview.datamodel.PDBEntry;
46 import jalview.datamodel.Sequence;
47 import jalview.datamodel.SequenceI;
48 import jalview.fts.api.FTSData;
49 import jalview.fts.core.FTSRestClient;
50 import jalview.fts.service.pdb.PDBFTSRestClient;
51 import jalview.fts.service.pdb.PDBFTSRestClientTest;
52 import jalview.fts.service.threedbeacons.TDBeaconsFTSRestClient;
53 import jalview.fts.threedbeacons.TDBeaconsFTSRestClientTest;
54 import jalview.gui.StructureViewer.ViewerType;
55 import jalview.gui.structurechooser.PDBStructureChooserQuerySource;
56 import jalview.io.DataSourceType;
57 import jalview.io.FileFormatException;
58 import jalview.io.FileFormatI;
59 import jalview.io.FileLoader;
60 import jalview.io.IdentifyFile;
61 import jalview.jbgui.FilterOption;
62 import jalview.structure.StructureImportSettings.TFType;
63 import junit.extensions.PA;
64
65 @Test(singleThreaded = true)
66 public class StructureChooserTest
67 {
68
69   @BeforeClass(alwaysRun = true)
70   public void setUpJvOptionPane()
71   {
72     JvOptionPane.setInteractiveMode(false);
73     JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
74   }
75
76   Sequence seq, upSeq, upSeq_nocanonical;
77
78   @BeforeMethod(alwaysRun = true)
79   public void setUp() throws Exception
80   {
81     seq = new Sequence("PDB|4kqy|4KQY|A", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 1,
82             26);
83     seq.createDatasetSequence();
84     for (int x = 1; x < 5; x++)
85     {
86       DBRefEntry dbRef = new DBRefEntry();
87       dbRef.setAccessionId("XYZ_" + x);
88       seq.addDBRef(dbRef);
89     }
90
91     PDBEntry dbRef = new PDBEntry();
92     dbRef.setId("1tim");
93
94     Vector<PDBEntry> pdbIds = new Vector<>();
95     pdbIds.add(dbRef);
96
97     seq.setPDBId(pdbIds);
98
99     // Uniprot sequence for 3D-Beacons mocks
100     upSeq = new Sequence("P38398",
101             "MDLSALRVEEVQNVINAMQKILECPICLELIKEPVSTKCDHIFCKFCMLKLLNQKKGPSQCPLCKNDITKRS\n"
102                     + "LQESTRFSQLVEELLKIICAFQLDTGLEYANSYNFAKKENNSPEHLKDEVSIIQSMGYRNRAKRLLQSEPEN\n"
103                     + "PSLQETSLSVQLSNLGTVRTLRTKQRIQPQKTSVYIELGSDSSEDTVNKATYCSVGDQELLQITPQGTRDEI\n"
104                     + "SLDSAKKAACEFSETDVTNTEHHQPSNNDLNTTEKRAAERHPEKYQGSSVSNLHVEPCGTNTHASSLQHENS\n"
105                     + "SLLLTKDRMNVEKAEFCNKSKQPGLARSQHNRWAGSKETCNDRRTPSTEKKVDLNADPLCERKEWNKQKLPC\n"
106                     + "SENPRDTEDVPWITLNSSIQKVNEWFSRSDELLGSDDSHDGESESNAKVADVLDVLNEVDEYSGSSEKIDLL\n"
107                     + "ASDPHEALICKSERVHSKSVESNIEDKIFGKTYRKKASLPNLSHVTENLIIGAFVTEPQIIQERPLTNKLKR\n"
108                     + "KRRPTSGLHPEDFIKKADLAVQKTPEMINQGTNQTEQNGQVMNITNSGHENKTKGDSIQNEKNPNPIESLEK\n"
109                     + "ESAFKTKAEPISSSISNMELELNIHNSKAPKKNRLRRKSSTRHIHALELVVSRNLSPPNCTELQIDSCSSSE\n"
110                     + "EIKKKKYNQMPVRHSRNLQLMEGKEPATGAKKSNKPNEQTSKRHDSDTFPELKLTNAPGSFTKCSNTSELKE\n"
111                     + "FVNPSLPREEKEEKLETVKVSNNAEDPKDLMLSGERVLQTERSVESSSISLVPGTDYGTQESISLLEVSTLG\n"
112                     + "KAKTEPNKCVSQCAAFENPKGLIHGCSKDNRNDTEGFKYPLGHEVNHSRETSIEMEESELDAQYLQNTFKVS\n"
113                     + "KRQSFAPFSNPGNAEEECATFSAHSGSLKKQSPKVTFECEQKEENQGKNESNIKPVQTVNITAGFPVVGQKD\n"
114                     + "KPVDNAKCSIKGGSRFCLSSQFRGNETGLITPNKHGLLQNPYRIPPLFPIKSFVKTKCKKNLLEENFEEHSM\n"
115                     + "SPEREMGNENIPSTVSTISRNNIRENVFKEASSSNINEVGSSTNEVGSSINEIGSSDENIQAELGRNRGPKL\n"
116                     + "NAMLRLGVLQPEVYKQSLPGSNCKHPEIKKQEYEEVVQTVNTDFSPYLISDNLEQPMGSSHASQVCSETPDD\n"
117                     + "LLDDGEIKEDTSFAENDIKESSAVFSKSVQKGELSRSPSPFTHTHLAQGYRRGAKKLESSEENLSSEDEELP\n"
118                     + "CFQHLLFGKVNNIPSQSTRHSTVATECLSKNTEENLLSLKNSLNDCSNQVILAKASQEHHLSEETKCSASLF\n"
119                     + "SSQCSELEDLTANTNTQDPFLIGSSKQMRHQSESQGVGLSDKELVSDDEERGTGLEENNQEEQSMDSNLGEA\n"
120                     + "ASGCESETSVSEDCSGLSSQSDILTTQQRDTMQHNLIKLQQEMAELEAVLEQHGSQPSNSYPSIISDSSALE\n"
121                     + "DLRNPEQSTSEKAVLTSQKSSEYPISQNPEGLSADKFEVSADSSTSKNKEPGVERSSPSKCPSLDDRWYMHS\n"
122                     + "CSGSLQNRNYPSQEELIKVVDVEEQQLEESGPHDLTETSYLPRQDLEGTPYLESGISLFSDDPESDPSEDRA\n"
123                     + "PESARVGNIPSSTSALKVPQLKVAESAQSPAAAHTTDTAGYNAMEESVSREKPELTASTERVNKRMSMVVSG\n"
124                     + "LTPEEFMLVYKFARKHHITLTNLITEETTHVVMKTDAEFVCERTLKYFLGIAGGKWVVSYFWVTQSIKERKM\n"
125                     + "LNEHDFEVRGDVVNGRNHQGPKRARESQDRKIFRGLEICCYGPFTNMPTDQLEWMVQLCGASVVKELSSFTL\n"
126                     + "GTGVHPIVVVQPDAWTEDNGFHAIGQMCEAPVVTREWVLDSVALYQCQELDTYLIPQIPHSHY\n"
127                     + "",
128             1, 1863);
129     upSeq.setDescription("Breast cancer type 1 susceptibility protein");
130     upSeq_nocanonical = new Sequence(upSeq);
131     upSeq.createDatasetSequence();
132     upSeq.addDBRef(new DBRefEntry("UNIPROT", "0", "P38398", null, true));
133
134     upSeq_nocanonical.createDatasetSequence();
135     // not a canonical reference
136     upSeq_nocanonical.addDBRef(
137             new DBRefEntry("UNIPROT", "0", "P38398", null, false));
138
139   }
140
141   @AfterMethod(alwaysRun = true)
142   public void tearDown() throws Exception
143   {
144     seq = null;
145     upSeq = null;
146     upSeq_nocanonical = null;
147   }
148
149   @Test(groups = { "Functional" })
150   public void populateFilterComboBoxTest() throws InterruptedException
151   {
152     TDBeaconsFTSRestClientTest.setMock();
153     PDBFTSRestClientTest.setMock();
154
155     SequenceI[] selectedSeqs = new SequenceI[] { seq };
156     StructureChooser sc = new StructureChooser(selectedSeqs, seq, null);
157     ThreadwaitFor(200, sc);
158
159     // if structures are not discovered then don't
160     // populate filter options
161     sc.populateFilterComboBox(false, false);
162     int optionsSize = sc.getCmbFilterOption().getItemCount();
163     System.out.println("Items (no data, no cache): ");
164     StringBuilder items = new StringBuilder();
165     for (int p = 0; p < optionsSize; p++)
166     {
167       items.append("- ")
168               .append(sc.getCmbFilterOption().getItemAt(p).getName())
169               .append("\n");
170
171     }
172     // report items when this fails - seems to be a race condition
173     Assert.assertEquals(items.toString(), optionsSize, 2);
174
175     sc.populateFilterComboBox(true, false);
176     optionsSize = sc.getCmbFilterOption().getItemCount();
177     assertTrue(optionsSize > 3); // if structures are found, filter options
178                                  // should be populated
179
180     sc.populateFilterComboBox(true, true);
181     assertTrue(sc.getCmbFilterOption().getSelectedItem() != null);
182     FilterOption filterOpt = (FilterOption) sc.getCmbFilterOption()
183             .getSelectedItem();
184     assertEquals("Cached Structures", filterOpt.getName());
185     FTSRestClient
186             .unMock((FTSRestClient) TDBeaconsFTSRestClient.getInstance());
187     FTSRestClient.unMock((FTSRestClient) PDBFTSRestClient.getInstance());
188
189   }
190
191   @Test(groups = { "Functional" })
192   public void displayTDBQueryTest() throws InterruptedException
193   {
194     TDBeaconsFTSRestClientTest.setMock();
195     PDBFTSRestClientTest.setMock();
196
197     SequenceI[] selectedSeqs = new SequenceI[] { upSeq_nocanonical };
198     StructureChooser sc = new StructureChooser(selectedSeqs,
199             upSeq_nocanonical, null);
200     // mock so should be quick. Exceptions from mocked PDBFTS are expected too
201     ThreadwaitFor(500, sc);
202
203     assertTrue(sc.isCanQueryTDB() && sc.isNotQueriedTDBYet());
204   }
205
206   @Test(groups = { "Network" })
207   public void fetchStructuresInfoTest()
208   {
209     FTSRestClient
210             .unMock((FTSRestClient) TDBeaconsFTSRestClient.getInstance());
211     PDBFTSRestClient.unMock((FTSRestClient) PDBFTSRestClient.getInstance());
212     SequenceI[] selectedSeqs = new SequenceI[] { seq };
213     StructureChooser sc = new StructureChooser(selectedSeqs, seq, null);
214     // not mocked, wait for 2s
215     ThreadwaitFor(2000, sc);
216
217     sc.fetchStructuresMetaData();
218     Collection<FTSData> ss = (Collection<FTSData>) PA.getValue(sc,
219             "discoveredStructuresSet");
220     assertNotNull(ss);
221     assertTrue(ss.size() > 0);
222   }
223
224   @Test(groups = { "Functional" })
225   public void fetchStructuresInfoMockedTest()
226   {
227     TDBeaconsFTSRestClientTest.setMock();
228     PDBFTSRestClientTest.setMock();
229     SequenceI[] selectedSeqs = new SequenceI[] { upSeq };
230     StructureChooser sc = new StructureChooser(selectedSeqs, seq, null);
231     ThreadwaitFor(500, sc);
232
233     sc.fetchStructuresMetaData();
234     Collection<FTSData> ss = (Collection<FTSData>) PA.getValue(sc,
235             "discoveredStructuresSet");
236     assertNotNull(ss);
237     assertTrue(ss.size() > 0);
238   }
239
240   private void ThreadwaitFor(int i, StructureChooser sc)
241   {
242     long timeout = i + System.currentTimeMillis();
243     while (!sc.isDialogVisible() && timeout > System.currentTimeMillis())
244     {
245       try
246       {
247         Thread.sleep(50);
248       } catch (InterruptedException x)
249       {
250
251       }
252     }
253
254   }
255
256   @Test(groups = { "Functional" })
257   public void sanitizeSeqNameTest()
258   {
259     String name = "ab_cdEF|fwxyz012349";
260     assertEquals(name,
261             PDBStructureChooserQuerySource.sanitizeSeqName(name));
262
263     // remove a [nn] substring
264     name = "abcde12[345]fg";
265     assertEquals("abcde12fg",
266             PDBStructureChooserQuerySource.sanitizeSeqName(name));
267
268     // remove characters other than a-zA-Z0-9 | or _
269     name = "ab[cd],.\t£$*!- \\\"@:e";
270     assertEquals("abcde",
271             PDBStructureChooserQuerySource.sanitizeSeqName(name));
272
273     name = "abcde12[345a]fg";
274     assertEquals("abcde12345afg",
275             PDBStructureChooserQuerySource.sanitizeSeqName(name));
276   }
277
278   @Test(groups = { "Functional" }, dataProvider = "openStructureFileParams")
279   public void openStructureFileForSequenceTest(String alfile, String seqid,
280           String sFilename, TFType tft, String paeFilename,
281           boolean showRefAnnotations, boolean doXferSettings,
282           ViewerType viewerType, int seqNum, int annNum, int viewerNum,
283           String propsFile)
284   {
285     Cache.loadProperties(
286             propsFile == null ? "test/jalview/io/testProps.jvprops"
287                     : propsFile);
288
289     Jalview.main(
290             propsFile == null ? null : new String[]
291             { "--props", propsFile });
292     if (Desktop.instance != null)
293       Desktop.instance.closeAll_actionPerformed(null);
294     JvOptionPane.setInteractiveMode(false);
295     JvOptionPane.setMockResponse(JvOptionPane.OK_OPTION);
296
297     FileLoader fileLoader = new FileLoader(true);
298     FileFormatI format = null;
299     File alFile = new File(alfile);
300     try
301     {
302       format = new IdentifyFile().identify(alFile, DataSourceType.FILE);
303     } catch (FileFormatException e1)
304     {
305       Assert.fail(
306               "Unknown file format for '" + alFile.getAbsolutePath() + "'");
307     }
308
309     AlignFrame af = fileLoader.LoadFileWaitTillLoaded(alFile,
310             DataSourceType.FILE, format);
311     AlignmentPanel ap = af.alignPanel;
312     Assert.assertNotNull("No alignPanel", ap);
313
314     AlignmentI al = ap.getAlignment();
315     Assert.assertNotNull(al);
316
317     SequenceI seq = al.findName(seqid);
318     Assert.assertNotNull("Sequence '" + seqid + "' not found in alignment",
319             seq);
320
321     StructureChooser.openStructureFileForSequence(null, null, ap, seq,
322             false, sFilename, tft, paeFilename, false, showRefAnnotations,
323             doXferSettings, viewerType);
324
325     List<SequenceI> seqs = al.getSequences();
326     Assert.assertNotNull(seqs);
327
328     Assert.assertEquals("Wrong number of sequences", seqNum, seqs.size());
329
330     AlignViewportI av = ap.getAlignViewport();
331     Assert.assertNotNull(av);
332
333     AlignmentAnnotation[] aas = al.getAlignmentAnnotation();
334     int visibleAnn = 0;
335     for (AlignmentAnnotation aa : aas)
336     {
337       if (aa.visible)
338         visibleAnn++;
339     }
340     Assert.assertEquals("Wrong number of viewed annotations", annNum,
341             visibleAnn);
342
343     if (viewerNum > -1)
344     {
345       try
346       {
347         Thread.sleep(100);
348       } catch (InterruptedException e)
349       {
350         // TODO Auto-generated catch block
351         e.printStackTrace();
352       }
353       List<StructureViewerBase> openViewers = Desktop.instance
354               .getStructureViewers(ap, null);
355       Assert.assertNotNull(openViewers);
356       Assert.assertEquals("Wrong number of structure viewers opened",
357               viewerNum, openViewers.size());
358     }
359
360     if (af != null)
361     {
362       af.setVisible(false);
363       af.dispose();
364     }
365   }
366
367   @DataProvider(name = "openStructureFileParams")
368   public Object[][] openStructureFileParams()
369   {
370     /*
371         String alFile,
372         String seqid,
373         String structureFilename,
374         TFType tft,
375         String paeFilename,
376         boolean showRefAnnotations,
377         boolean doXferSettings, // false for Commands
378         ViewerType viewerType,
379         int seqNum,
380         int annNum,
381         int viewerNum,
382         String propsFile
383      */
384     return new Object[][] {
385         /*
386         */
387         { "examples/uniref50.fa", "FER1_SPIOL",
388             "examples/AlphaFold/AF-P00221-F1-model_v4.cif", TFType.DEFAULT,
389             "examples/AlphaFold/AF-P00221-F1-predicted_aligned_error_v4.json",
390             true, false, null, 15, 7, 0, null },
391         { "examples/uniref50.fa", "FER1_SPIOL",
392             "examples/AlphaFold/AF-P00221-F1-model_v4.cif", TFType.PLDDT,
393             "examples/AlphaFold/AF-P00221-F1-predicted_aligned_error_v4.json",
394             true, false, null, 15, 7, 0, null },
395         { "examples/uniref50.fa", "FER1_SPIOL",
396             "examples/AlphaFold/AF-P00221-F1-model_v4.cif", TFType.PLDDT,
397             "examples/AlphaFold/AF-P00221-F1-predicted_aligned_error_v4.json",
398             false, false, null, 15, 4, 0, null },
399         { "examples/uniref50.fa", "FER1_SPIOL",
400             "examples/AlphaFold/AF-P00221-F1-model_v4.cif", TFType.DEFAULT,
401             "examples/AlphaFold/AF-P00221-F1-predicted_aligned_error_v4.json",
402             true, false, ViewerType.JMOL, 15, 7, 1, null },
403         { "examples/uniref50.fa", "FER1_SPIOL",
404             "examples/AlphaFold/AF-P00221-F1-model_v4.cif", TFType.PLDDT,
405             "examples/AlphaFold/AF-P00221-F1-predicted_aligned_error_v4.json",
406             true, false, ViewerType.JMOL, 15, 7, 1, null },
407         { "examples/uniref50.fa", "FER1_SPIOL",
408             "examples/AlphaFold/AF-P00221-F1-model_v4.cif", TFType.PLDDT,
409             "examples/AlphaFold/AF-P00221-F1-predicted_aligned_error_v4.json",
410             false, false, ViewerType.JMOL, 15, 4, 1, null }, };
411   }
412
413 }