dd570c065bf3d6e71af3fdd818ee8081d9ced580
[jalview.git] / src / jalview / gui / AppVarna.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8)
3  * Copyright (C) 2012 J Procter, AM Waterhouse, LM Lui, J Engelhardt, G Barton, M Clamp, S Searle
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 of the License, or (at your option) any later version.
10  *  
11  * Jalview is distributed in the hope that it will be useful, but 
12  * WITHOUT ANY WARRANTY; without even the implied warranty 
13  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
14  * PURPOSE.  See the GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 package jalview.gui;
19
20 import java.util.*;
21 import java.util.regex.Matcher;
22 import java.util.regex.Pattern;
23 import java.awt.*;
24
25 import javax.swing.*;
26
27 import jalview.bin.Cache;
28 import jalview.datamodel.*;
29 import jalview.structure.*;
30 import jalview.util.ShiftList;
31 import fr.orsay.lri.varna.VARNAPanel;
32 import fr.orsay.lri.varna.exceptions.ExceptionFileFormatOrSyntax;
33 import fr.orsay.lri.varna.exceptions.ExceptionUnmatchedClosingParentheses;
34 import fr.orsay.lri.varna.interfaces.InterfaceVARNAListener;
35 import fr.orsay.lri.varna.interfaces.InterfaceVARNASelectionListener;
36 import fr.orsay.lri.varna.models.BaseList;
37 import fr.orsay.lri.varna.models.VARNAConfig;
38 import fr.orsay.lri.varna.models.annotations.HighlightRegionAnnotation;
39 import fr.orsay.lri.varna.models.rna.ModeleBase;
40 import fr.orsay.lri.varna.models.rna.RNA;
41
42 public class AppVarna extends JInternalFrame implements
43         InterfaceVARNAListener, SelectionListener,
44         SecondaryStructureListener// implements
45                                   // Runnable,SequenceStructureBinding,
46                                   // ViewSetProvider
47         , InterfaceVARNASelectionListener, VamsasSource
48
49 {
50   AppVarnaBinding vab;
51
52   VARNAPanel varnaPanel;
53
54   public String name;
55
56   public StructureSelectionManager ssm;
57
58   /*
59    * public AppVarna(){ vab = new AppVarnaBinding(); initVarna(); }
60    */
61
62   AlignmentPanel ap;
63
64   public AppVarna(String sname, SequenceI seq, String strucseq,
65           String struc, String name, AlignmentPanel ap)
66   {
67           System.out.println("je suis là (AppVarna!!");
68           System.out.println("1:"+sname);
69           System.out.println("2:"+seq);
70           System.out.println("3:"+strucseq);
71           System.out.println("4:"+struc);
72           System.out.println("5:"+name);
73           System.out.println("6:"+ap);
74     this.ap = ap;
75     ArrayList<RNA> rnaList = new ArrayList<RNA>();
76     RNA rna1 = new RNA(name);
77     try
78     {
79     System.out.println("ou ici ?");
80       rna1.setRNA(strucseq, replaceOddGaps(struc));
81       System.out.println("La séquence est :"+rna1.getSeq());
82       System.out.println("La séquence est :"+struc);
83       System.out.println("La séquence est :"+replaceOddGaps(struc).toString());
84     } catch (ExceptionUnmatchedClosingParentheses e2)
85     {
86       e2.printStackTrace();
87     } catch (ExceptionFileFormatOrSyntax e3)
88     {
89       e3.printStackTrace();
90     }
91     RNA trim = trimRNA(rna1, "trimmed " + sname);
92     rnaList.add(trim);
93     rnaList.add(rna1);
94     
95     rnas.put(seq, rna1);
96     rnas.put(seq, trim);
97     rna1.setName(sname + " (with gaps)");
98
99     {
100       seqs.put(trim, seq);
101       seqs.put(rna1, seq);
102       
103       /**
104        * if (false || seq.getStart()!=1) { for (RNA rshift:rnaList) { ShiftList
105        * shift=offsets.get(rshift); if (shift==null) { offsets.put(rshift,
106        * shift=new ShiftList());} shift.addShift(1, seq.getStart()-1);
107        * offsetsInv.put(rshift, shift.getInverse()); } }
108        **/
109     }
110     vab = new AppVarnaBinding(rnaList);
111     // vab = new AppVarnaBinding(seq,struc);
112     // System.out.println("Hallo: "+name);
113     this.name = sname + " trimmed to " + name;
114     initVarna();
115    
116     ssm = ap.getStructureSelectionManager();
117     System.out.println(ssm.toString());
118     ssm.addStructureViewerListener(this);
119     ssm.addSelectionListener(this);
120   }
121
122   public void initVarna()
123   {
124           System.out.println("initialisation VANRA");
125     // vab.setFinishedInit(false);
126     varnaPanel = vab.get_varnaPanel();
127     setBackground(Color.white);
128     JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true,
129             vab.getListPanel(), varnaPanel);
130     getContentPane().setLayout(new BorderLayout());
131     getContentPane().add(split, BorderLayout.CENTER);
132     // getContentPane().add(vab.getTools(), BorderLayout.NORTH);
133     varnaPanel.addVARNAListener(this);
134     varnaPanel.addSelectionListener(this);
135     jalview.gui.Desktop.addInternalFrame(this, "VARNA -" + name,
136             getBounds().width, getBounds().height);
137     this.pack();
138     showPanel(true);
139     System.out.println("Sortie initialisation VANRA");
140   }
141
142   public String replaceOddGaps(String oldStr)
143   {
144     String patternStr = "[^([{<>}])]";
145     String replacementStr = ".";
146     Pattern pattern = Pattern.compile(patternStr);
147     Matcher matcher = pattern.matcher(oldStr);
148     String newStr = matcher.replaceAll(replacementStr);
149     return newStr;
150   }
151
152   public RNA trimRNA(RNA rna, String name)
153   {
154     ShiftList offset = new ShiftList();
155     
156     RNA rnaTrim = new RNA(name);
157     try
158     {
159       rnaTrim.setRNA(rna.getSeq(), replaceOddGaps(rna.getStructDBN()));
160     } catch (ExceptionUnmatchedClosingParentheses e2)
161     {
162       e2.printStackTrace();
163     } catch (ExceptionFileFormatOrSyntax e3)
164     {
165       e3.printStackTrace();
166     }
167
168     StringBuffer seq = new StringBuffer(rnaTrim.getSeq());
169     StringBuffer struc = new StringBuffer(rnaTrim.getStructDBN());
170     int ofstart = -1, sleng = rnaTrim.getSeq().length();
171     for (int i = 0; i < sleng; i++)
172     {
173       // TODO: Jalview utility for gap detection java.utils.isGap()
174       // TODO: Switch to jalview rna datamodel
175       if (jalview.util.Comparison.isGap(seq.charAt(i)))
176       {
177         if (ofstart == -1)
178         {
179           ofstart = i;
180         }
181         if (!rnaTrim.findPair(i).isEmpty())
182         {
183           int m = rnaTrim.findPair(i).get(1);
184           int l = rnaTrim.findPair(i).get(0);
185
186           struc.replace(m, m + 1, "*");
187           struc.replace(l, l + 1, "*");
188         }
189         else
190         {
191           struc.replace(i, i + 1, "*");
192         }
193       }
194       else
195       {
196         if (ofstart > -1)
197         {
198           offset.addShift(offset.shift(ofstart), ofstart - i);
199           ofstart = -1;
200         }
201       }
202     }
203     // final gap
204     if (ofstart > -1)
205     {
206       offset.addShift(offset.shift(ofstart), ofstart - sleng);
207       ofstart = -1;
208     }
209     String newSeq = rnaTrim.getSeq().replace("-", "");
210     rnaTrim.getSeq().replace(".", "");
211     String newStruc = struc.toString().replace("*", "");
212
213     try
214     {
215       rnaTrim.setRNA(newSeq, newStruc);
216       registerOffset(rnaTrim, offset);
217     } catch (ExceptionUnmatchedClosingParentheses e)
218     {
219       // TODO Auto-generated catch block
220       e.printStackTrace();
221     } catch (ExceptionFileFormatOrSyntax e)
222     {
223       // TODO Auto-generated catch block
224       e.printStackTrace();
225     }
226     return rnaTrim;
227   }
228
229   // needs to be many-many
230   Map<RNA, SequenceI> seqs = new Hashtable<RNA, SequenceI>();
231
232   Map<SequenceI, RNA> rnas = new Hashtable<SequenceI, RNA>();
233
234   Map<RNA, ShiftList> offsets = new Hashtable<RNA, ShiftList>();
235
236   Map<RNA, ShiftList> offsetsInv = new Hashtable<RNA, ShiftList>();
237
238   private void registerOffset(RNA rnaTrim, ShiftList offset)
239   {
240     offsets.put(rnaTrim, offset);
241     offsetsInv.put(rnaTrim, offset.getInverse());
242   }
243
244   public void showPanel(boolean show)
245   {
246     this.setVisible(show);
247   }
248
249   private boolean _started = false;
250
251   public void run()
252   {
253     _started = true;
254
255     try
256     {
257       initVarna();
258     } catch (OutOfMemoryError oomerror)
259     {
260       new OOMWarning("When trying to open the Varna viewer!", oomerror);
261     } catch (Exception ex)
262     {
263       Cache.log.error("Couldn't open Varna viewer!", ex);
264     }
265   }
266
267   @Override
268   public void onUINewStructure(VARNAConfig v, RNA r)
269   {
270
271   }
272
273   @Override
274   public void onWarningEmitted(String s)
275   {
276     // TODO Auto-generated method stub
277
278   }
279
280   private class VarnaHighlighter
281   {
282     private HighlightRegionAnnotation _lastHighlight;
283
284     private RNA _lastRNAhighlighted = null;
285
286     public void highlightRegion(RNA rna, int start, int end)
287     {
288       clearSelection(null);
289       HighlightRegionAnnotation highlight = new HighlightRegionAnnotation(
290               rna.getBasesBetween(start, end));
291       rna.addHighlightRegion(highlight);
292       _lastHighlight = highlight;
293       _lastRNAhighlighted = rna;
294
295     }
296
297     public HighlightRegionAnnotation getLastHighlight()
298     {
299       return _lastHighlight;
300     }
301
302     public RNA getLastRNA()
303     {
304       return _lastRNAhighlighted;
305     }
306
307     public void clearSelection(AppVarnaBinding vab)
308     {
309       if (_lastRNAhighlighted != null)
310       {
311         _lastRNAhighlighted.removeHighlightRegion(_lastHighlight);
312         if (vab != null)
313         {
314           vab.updateSelectedRNA(_lastRNAhighlighted);
315         }
316         _lastRNAhighlighted = null;
317         _lastHighlight = null;
318
319       }
320     }
321   }
322
323   VarnaHighlighter mouseOverHighlighter = new VarnaHighlighter(),
324           selectionHighlighter = new VarnaHighlighter();
325
326   /**
327    * If a mouseOver event from the AlignmentPanel is noticed the currently
328    * selected RNA in the VARNA window is highlighted at the specific position.
329    * To be able to remove it before the next highlight it is saved in
330    * _lastHighlight
331    */
332   @Override
333   public void mouseOverSequence(SequenceI sequence, int index)
334   {
335     RNA rna = vab.getSelectedRNA();
336     if (seqs.get(rna) == sequence)
337     {
338       ShiftList shift = offsets.get(rna);
339       if (shift != null)
340       {
341         // System.err.print("Orig pos:"+index);
342         index = shift.shift(index);
343         // System.err.println("\nFinal pos:"+index);
344       }
345       mouseOverHighlighter.highlightRegion(rna, index, index);
346       vab.updateSelectedRNA(rna);
347     }
348   }
349
350   @Override
351   public void onStructureRedrawn()
352   {
353     // TODO Auto-generated method stub
354
355   }
356
357   @Override
358   public void selection(SequenceGroup seqsel, ColumnSelection colsel,
359           SelectionSource source)
360   {
361     if (source != ap.av)
362     {
363       // ignore events from anything but our parent alignpanel
364       // TODO - reuse many-one panel-view system in jmol viewer
365       return;
366     }
367     if (seqsel != null && seqsel.getSize() > 0)
368     {
369       int start = seqsel.getStartRes(), end = seqsel.getEndRes();
370       RNA rna = vab.getSelectedRNA();
371       ShiftList shift = offsets.get(rna);
372       if (shift != null)
373       {
374         start = shift.shift(start);
375         end = shift.shift(end);
376       }
377       selectionHighlighter.highlightRegion(rna, start, end);
378       selectionHighlighter.getLastHighlight().setOutlineColor(
379               seqsel.getOutlineColour());
380       // TODO - translate column markings to positions on structure if present.
381       vab.updateSelectedRNA(rna);
382     }
383     else
384     {
385       selectionHighlighter.clearSelection(vab);
386     }
387   }
388
389   @Override
390   public void onHoverChanged(ModeleBase arg0, ModeleBase arg1)
391   {
392     RNA rna = vab.getSelectedRNA();
393     ShiftList shift = offsetsInv.get(rna);
394     SequenceI seq = seqs.get(rna);
395     if (arg1 != null && seq != null)
396     {
397       if (shift != null)
398       {
399         int i = shift.shift(arg1.getIndex());
400         // System.err.println("shifted "+(arg1.getIndex())+" to "+i);
401         ssm.mouseOverVamsasSequence(seq, i, this);
402       }
403       else
404       {
405         ssm.mouseOverVamsasSequence(seq, arg1.getIndex(), this);
406       }
407     }
408   }
409
410   @Override
411   public void onSelectionChanged(BaseList arg0, BaseList arg1, BaseList arg2)
412   {
413     // TODO translate selected regions in VARNA to a selection on the
414     // alignpanel.
415
416   }
417
418 }