JAL-3855 detect an alphafold model and import its temperature factor as reliability
[jalview.git] / test / mc_view / PDBChainTest.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 mc_view;
22
23 import static org.testng.AssertJUnit.assertEquals;
24 import static org.testng.AssertJUnit.assertFalse;
25 import static org.testng.AssertJUnit.assertSame;
26 import static org.testng.AssertJUnit.assertTrue;
27
28 import jalview.analysis.AlignSeq;
29 import jalview.datamodel.AlignmentAnnotation;
30 import jalview.datamodel.Sequence;
31 import jalview.datamodel.SequenceFeature;
32 import jalview.datamodel.SequenceI;
33 import jalview.gui.JvOptionPane;
34 import jalview.schemes.ColourSchemeI;
35 import jalview.schemes.TaylorColourScheme;
36 import jalview.structure.StructureImportSettings;
37
38 import java.awt.Color;
39 import java.util.List;
40 import java.util.Vector;
41
42 import org.testng.annotations.BeforeClass;
43 import org.testng.annotations.BeforeMethod;
44 import org.testng.annotations.Test;
45
46 public class PDBChainTest
47 {
48
49   @BeforeClass(alwaysRun = true)
50   public void setUpJvOptionPane()
51   {
52     JvOptionPane.setInteractiveMode(false);
53     JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
54   }
55
56   PDBChain c;
57
58   final Atom a1 = new Atom(1f, 2f, 3f);
59
60   final Atom a2 = new Atom(5f, 6f, 4f);
61
62   final Atom a3 = new Atom(2f, 5f, 6f);
63
64   final Atom a4 = new Atom(2f, 1f, 7f);
65
66   @BeforeMethod(alwaysRun = true)
67   public void setUp()
68   {
69     System.out.println("setup");
70     StructureImportSettings.setShowSeqFeatures(true);
71     c = new PDBChain("1GAQ", "A", false);
72   }
73
74   @Test(groups = { "Functional" })
75   public void testGetNewlineString()
76   {
77     assertEquals(System.lineSeparator(), c.getNewlineString());
78     c.setNewlineString("gaga");
79     assertEquals("gaga", c.getNewlineString());
80   }
81
82   @Test(groups = { "Functional" })
83   public void testPrint()
84   {
85     c.offset = 7;
86
87     a1.resName = "GLY";
88     a1.resNumber = 23;
89     a2.resName = "GLU";
90     a2.resNumber = 34;
91     a3.resName = "ASP";
92     a3.resNumber = 41;
93
94     Vector<Bond> v = new Vector<>();
95     v.add(new Bond(a1, a2));
96     v.add(new Bond(a2, a3));
97     v.add(new Bond(a3, a1));
98     c.bonds = v;
99
100     String printed = c.print();
101     String nl = System.lineSeparator();
102     assertEquals("GLY 23 7" + nl + "GLU 34 7" + nl + "ASP 41 7" + nl,
103             printed);
104   }
105
106   /**
107    * Test the method that constructs a Bond between two atoms and adds it to the
108    * chain's list of bonds
109    */
110   @Test(groups = { "Functional" })
111   public void testMakeBond()
112   {
113     /*
114      * Add a bond from a1 to a2
115      */
116     c.makeBond(a1, a2);
117     assertEquals(1, c.bonds.size());
118     Bond b1 = c.bonds.get(0);
119     assertSame(a1, b1.at1);
120     assertSame(a2, b1.at2);
121     assertEquals(1f, b1.start[0], 0.0001f);
122     assertEquals(2f, b1.start[1], 0.0001f);
123     assertEquals(3f, b1.start[2], 0.0001f);
124     assertEquals(5f, b1.end[0], 0.0001f);
125     assertEquals(6f, b1.end[1], 0.0001f);
126     assertEquals(4f, b1.end[2], 0.0001f);
127
128     /*
129      * Add another bond from a2 to a1
130      */
131     c.makeBond(a2, a1);
132     assertEquals(2, c.bonds.size());
133     assertSame(b1, c.bonds.get(0));
134     Bond b2 = c.bonds.get(1);
135     assertSame(a2, b2.at1);
136     assertSame(a1, b2.at2);
137     assertEquals(5f, b2.start[0], 0.0001f);
138     assertEquals(6f, b2.start[1], 0.0001f);
139     assertEquals(4f, b2.start[2], 0.0001f);
140     assertEquals(1f, b2.end[0], 0.0001f);
141     assertEquals(2f, b2.end[1], 0.0001f);
142     assertEquals(3f, b2.end[2], 0.0001f);
143   }
144
145   @Test(groups = { "Functional" })
146   public void testSetChainColours_colour()
147   {
148     c.makeBond(a1, a2);
149     c.makeBond(a2, a3);
150     c.setChainColours(Color.PINK);
151     assertEquals(2, c.bonds.size());
152     assertEquals(Color.PINK, c.bonds.get(0).startCol);
153     assertEquals(Color.PINK, c.bonds.get(0).endCol);
154     assertEquals(Color.PINK, c.bonds.get(1).startCol);
155     assertEquals(Color.PINK, c.bonds.get(1).endCol);
156   }
157
158   /**
159    * Test setting bond start/end colours based on a colour scheme i.e. colour by
160    * residue
161    */
162   @Test(groups = { "Functional" })
163   public void testSetChainColours_colourScheme()
164   {
165     Color alaColour = new Color(204, 255, 0);
166     Color glyColour = new Color(255, 153, 0);
167     a1.resName = "ALA";
168     a2.resName = "GLY";
169     a3.resName = "XXX"; // no colour defined
170     c.makeBond(a1, a2);
171     c.makeBond(a2, a1);
172     c.makeBond(a2, a3);
173     ColourSchemeI cs = new TaylorColourScheme();
174     c.setChainColours(cs);
175     // bond a1 to a2
176     Bond b = c.bonds.get(0);
177     assertEquals(alaColour, b.startCol);
178     assertEquals(glyColour, b.endCol);
179     // bond a2 to a1
180     b = c.bonds.get(1);
181     assertEquals(glyColour, b.startCol);
182     assertEquals(alaColour, b.endCol);
183     // bond a2 to a3 - no colour found for a3
184     // exception handling defaults to gray
185     b = c.bonds.get(2);
186     assertEquals(Color.gray, b.startCol);
187     assertEquals(Color.gray, b.endCol);
188   }
189
190   @Test(groups = { "Functional" })
191   public void testGetChargeColour()
192   {
193     assertEquals(Color.red, PDBChain.getChargeColour("ASP"));
194     assertEquals(Color.red, PDBChain.getChargeColour("GLU"));
195     assertEquals(Color.blue, PDBChain.getChargeColour("LYS"));
196     assertEquals(Color.blue, PDBChain.getChargeColour("ARG"));
197     assertEquals(Color.yellow, PDBChain.getChargeColour("CYS"));
198     assertEquals(Color.lightGray, PDBChain.getChargeColour("ALA"));
199     assertEquals(Color.lightGray, PDBChain.getChargeColour(null));
200   }
201
202   /**
203    * Test the method that sets bond start/end colours by residue charge property
204    */
205   @Test(groups = { "Functional" })
206   public void testSetChargeColours()
207   {
208     a1.resName = "ASP"; // red
209     a2.resName = "LYS"; // blue
210     a3.resName = "CYS"; // yellow
211     a4.resName = "ALA"; // no colour (light gray)
212     c.makeBond(a1, a2);
213     c.makeBond(a2, a3);
214     c.makeBond(a3, a4);
215     c.setChargeColours();
216     assertEquals(3, c.bonds.size());
217     // bond a1 to a2
218     Bond b = c.bonds.get(0);
219     assertEquals(Color.red, b.startCol);
220     assertEquals(Color.blue, b.endCol);
221     // bond a2 to a3
222     b = c.bonds.get(1);
223     assertEquals(Color.blue, b.startCol);
224     assertEquals(Color.yellow, b.endCol);
225     // bond a3 to a4
226     b = c.bonds.get(2);
227     assertEquals(Color.yellow, b.startCol);
228     assertEquals(Color.lightGray, b.endCol);
229   }
230
231   /**
232    * Test the method that converts the raw list of atoms to a list of residues
233    */
234   @Test(groups = { "Functional" })
235   public void testMakeResidueList_noAnnotation()
236   {
237     Vector<Atom> atoms = new Vector<>();
238     c.atoms = atoms;
239     c.isNa = true;
240     atoms.add(makeAtom(4, "N", "MET"));
241     atoms.add(makeAtom(4, "CA", "MET"));
242     atoms.add(makeAtom(4, "C", "MET"));
243     atoms.add(makeAtom(5, "O", "LYS"));
244     atoms.add(makeAtom(5, "N", "LYS"));
245     atoms.add(makeAtom(5, "CA", "LYS"));
246     atoms.add(makeAtom(6, "O", "LEU"));
247     atoms.add(makeAtom(6, "N", "LEU"));
248     atoms.add(makeAtom(6, "CA", "LEU"));
249
250     c.makeResidueList(false);
251
252     /*
253      * check sequence constructed
254      */
255     assertEquals("MKL", c.sequence.getSequenceAsString());
256     assertFalse(c.isNa);
257     assertEquals(3, c.residues.size());
258
259     /*
260      * check sequence features
261      */
262     List<SequenceFeature> sfs = c.sequence.getSequenceFeatures();
263     assertEquals(3, sfs.size());
264     assertEquals("RESNUM", sfs.get(0).type);
265     assertEquals("MET:4 1gaqA", sfs.get(0).description);
266     assertEquals(4, sfs.get(0).begin);
267     assertEquals(4, sfs.get(0).end);
268     assertEquals("RESNUM", sfs.get(0).type);
269     assertEquals("LYS:5 1gaqA", sfs.get(1).description);
270     assertEquals(5, sfs.get(1).begin);
271     assertEquals(5, sfs.get(1).end);
272     assertEquals("LEU:6 1gaqA", sfs.get(2).description);
273     assertEquals(6, sfs.get(2).begin);
274     assertEquals(6, sfs.get(2).end);
275   }
276
277   private Atom makeAtom(int resnum, String name, String resname)
278   {
279     Atom a = new Atom(1f, 2f, 3f);
280     a.resNumber = resnum;
281     a.resNumIns = String.valueOf(resnum);
282     a.name = name;
283     a.resName = resname;
284     a.chain = "A";
285     return a;
286   }
287
288   /**
289    * Test the method that converts the raw list of atoms to a list of residues,
290    * including parsing of tempFactor to an alignment annotation
291    */
292   @Test(groups = { "Functional" })
293   public void testMakeResidueList_withTempFactor()
294   {
295     Vector<Atom> atoms = new Vector<>();
296     c.atoms = atoms;
297     atoms.add(makeAtom(4, "N", "MET"));
298     atoms.get(atoms.size() - 1).tfactor = 1f;
299     atoms.add(makeAtom(4, "CA", "MET"));
300     atoms.get(atoms.size() - 1).tfactor = 2f;
301     atoms.add(makeAtom(4, "C", "MET"));
302     atoms.get(atoms.size() - 1).tfactor = 3f;
303     atoms.add(makeAtom(5, "O", "LYS"));
304     atoms.get(atoms.size() - 1).tfactor = 7f;
305     atoms.add(makeAtom(5, "N", "LYS"));
306     atoms.get(atoms.size() - 1).tfactor = 8f;
307     atoms.add(makeAtom(5, "CA", "LYS"));
308     atoms.get(atoms.size() - 1).tfactor = 9f;
309     atoms.add(makeAtom(6, "O", "LEU"));
310     atoms.get(atoms.size() - 1).tfactor = -4f;
311     atoms.add(makeAtom(6, "N", "LEU"));
312     atoms.get(atoms.size() - 1).tfactor = 5f;
313     atoms.add(makeAtom(6, "CA", "LEU"));
314     atoms.get(atoms.size() - 1).tfactor = 6f;
315
316     /*
317      * make residues including temp factor annotation
318      */
319     c.makeResidueList(true);
320
321     /*
322      * Verify annotations; note the tempFactor is read from the first atom in
323      * each residue i.e. we expect values 1, 7, -4 for the residues
324      */
325     AlignmentAnnotation[] ann = c.sequence.getAnnotation();
326     assertEquals(1, ann.length);
327     assertEquals("Temperature Factor", ann[0].label);
328     assertEquals("Temperature Factor for 1gaqA", ann[0].description);
329     assertSame(c.sequence, ann[0].sequenceRef);
330     assertEquals(AlignmentAnnotation.LINE_GRAPH, ann[0].graph);
331     assertEquals(-4f, ann[0].graphMin, 0.001f);
332     assertEquals(7f, ann[0].graphMax, 0.001f);
333     assertEquals(3, ann[0].annotations.length);
334     assertEquals(1f, ann[0].annotations[0].value, 0.001f);
335     assertEquals(7f, ann[0].annotations[1].value, 0.001f);
336     assertEquals(-4f, ann[0].annotations[2].value, 0.001f);
337   }
338
339   /**
340    * Test the method that constructs bonds between successive residues' CA or P
341    * atoms
342    */
343   @Test(groups = { "Functional" })
344   public void testMakeCaBondList()
345   {
346     c.isNa = true;
347     Vector<Atom> atoms = new Vector<>();
348     c.atoms = atoms;
349     atoms.add(makeAtom(4, "N", "MET"));
350     atoms.add(makeAtom(4, "CA", "MET"));
351     atoms.add(makeAtom(5, "CA", "ASP"));
352     atoms.add(makeAtom(5, "O", "ASP"));
353     atoms.add(makeAtom(6, "CA", "GLY"));
354     atoms.add(makeAtom(6, "N", "GLY"));
355
356     // have to make residue list first!
357     c.makeResidueList(false);
358     assertFalse(c.isNa);
359     c.isNa = true;
360
361     c.makeCaBondList();
362     assertEquals(2, c.bonds.size());
363     Bond b = c.bonds.get(0);
364     assertSame(c.atoms.get(1), b.at1);
365     assertSame(c.atoms.get(2), b.at2);
366     b = c.bonds.get(1);
367     assertSame(c.atoms.get(2), b.at1);
368     assertSame(c.atoms.get(4), b.at2);
369
370     // isNa flag is _not_ reset by this method!
371     assertTrue(c.isNa);
372   }
373
374   @Test(groups = { "Functional" })
375   public void testMakeCaBondList_nucleotide()
376   {
377     c.isNa = false;
378     Vector<Atom> atoms = new Vector<>();
379     c.atoms = atoms;
380     atoms.add(makeAtom(4, "N", "G"));
381     atoms.add(makeAtom(4, "P", "G"));
382     atoms.add(makeAtom(5, "P", "C"));
383     atoms.add(makeAtom(5, "O", "C"));
384     atoms.add(makeAtom(6, "P", "T"));
385     atoms.add(makeAtom(6, "N", "T"));
386
387     // have to make residue list first!
388     c.makeResidueList(false);
389     assertEquals("GCT", c.sequence.getSequenceAsString());
390
391     c.makeCaBondList();
392     assertEquals(2, c.bonds.size());
393     Bond b = c.bonds.get(0);
394     assertSame(c.atoms.get(1), b.at1);
395     assertSame(c.atoms.get(2), b.at2);
396     b = c.bonds.get(1);
397     assertSame(c.atoms.get(2), b.at1);
398     assertSame(c.atoms.get(4), b.at2);
399
400     assertTrue(c.isNa);
401   }
402
403   /**
404    * Test the method that updates atoms with their alignment positions
405    */
406   @Test(groups = { "Functional" })
407   public void testMakeExactMapping()
408   {
409     Vector<Atom> atoms = new Vector<>();
410     c.atoms = atoms;
411     atoms.add(makeAtom(4, "N", "MET"));
412     atoms.add(makeAtom(4, "CA", "MET"));
413     atoms.add(makeAtom(5, "CA", "ASP"));
414     atoms.add(makeAtom(5, "O", "ASP"));
415     atoms.add(makeAtom(6, "CA", "GLY"));
416     atoms.add(makeAtom(6, "N", "GLY"));
417     c.makeResidueList(false);
418     assertEquals("MDG", c.sequence.getSequenceAsString());
419     SequenceI s1 = new Sequence("Seq1", "MDG");
420     SequenceI s2 = new Sequence("Seq2", "MDG");
421     AlignSeq alignSeq = AlignSeq.doGlobalNWAlignment(s1, s2, AlignSeq.PEP);
422     SequenceI seq3 = new Sequence("Seq3", "--M-DG");
423     c.makeExactMapping(alignSeq, seq3);
424
425     int pos = 0;
426     for (Residue res : c.residues)
427     {
428       for (Atom a : res.atoms)
429       {
430         assertEquals(pos, a.alignmentMapping);
431       }
432       pos++;
433     }
434   }
435 }