JAL-2738 copy to spikes/mungo
[jalview.git] / src / jalview / gui / StructureViewer.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 jalview.api.structures.JalviewStructureDisplayI;
24 import jalview.bin.Cache;
25 import jalview.datamodel.PDBEntry;
26 import jalview.datamodel.SequenceI;
27 import jalview.datamodel.StructureViewerModel;
28 import jalview.structure.StructureSelectionManager;
29
30 import java.awt.Rectangle;
31 import java.util.ArrayList;
32 import java.util.List;
33
34 /**
35  * proxy for handling structure viewers.
36  * 
37  * this allows new views to be created with the currently configured viewer, the
38  * preferred viewer to be set/read and existing views created previously with a
39  * particular viewer to be recovered
40  * 
41  * @author jprocter
42  */
43 public class StructureViewer
44 {
45   StructureSelectionManager ssm;
46
47   public enum ViewerType
48   {
49     JMOL, CHIMERA
50   };
51
52   public ViewerType getViewerType()
53   {
54     String viewType = Cache.getDefault(Preferences.STRUCTURE_DISPLAY,
55             ViewerType.JMOL.name());
56     return ViewerType.valueOf(viewType);
57   }
58
59   public void setViewerType(ViewerType type)
60   {
61     Cache.setProperty(Preferences.STRUCTURE_DISPLAY, type.name());
62   }
63
64   public StructureViewer(
65           StructureSelectionManager structureSelectionManager)
66   {
67     ssm = structureSelectionManager;
68   }
69
70   /**
71    * View multiple PDB entries, each with associated sequences
72    * 
73    * @param pdbs
74    * @param seqsForPdbs
75    * @param ap
76    * @return
77    */
78   public JalviewStructureDisplayI viewStructures(PDBEntry[] pdbs,
79           SequenceI[][] seqsForPdbs, AlignmentPanel ap)
80   {
81     JalviewStructureDisplayI viewer = onlyOnePdb(pdbs, seqsForPdbs, ap);
82     if (viewer != null)
83     {
84       return viewer;
85     }
86     return viewStructures(getViewerType(), pdbs, seqsForPdbs, ap);
87   }
88
89   /**
90    * A strictly temporary method pending JAL-1761 refactoring. Determines if all
91    * the passed PDB entries are the same (this is the case if selected sequences
92    * to view structure for are chains of the same structure). If so, calls the
93    * single-pdb version of viewStructures and returns the viewer, else returns
94    * null.
95    * 
96    * @param pdbs
97    * @param seqsForPdbs
98    * @param ap
99    * @return
100    */
101   private JalviewStructureDisplayI onlyOnePdb(PDBEntry[] pdbs,
102           SequenceI[][] seqsForPdbs, AlignmentPanel ap)
103   {
104     List<SequenceI> seqs = new ArrayList<SequenceI>();
105     if (pdbs == null || pdbs.length == 0)
106     {
107       return null;
108     }
109     int i = 0;
110     String firstFile = pdbs[0].getFile();
111     for (PDBEntry pdb : pdbs)
112     {
113       String pdbFile = pdb.getFile();
114       if (pdbFile == null || !pdbFile.equals(firstFile))
115       {
116         return null;
117       }
118       SequenceI[] pdbseqs = seqsForPdbs[i++];
119       if (pdbseqs != null)
120       {
121         for (SequenceI sq : pdbseqs)
122         {
123           seqs.add(sq);
124         }
125       }
126     }
127     return viewStructures(pdbs[0], seqs.toArray(new SequenceI[seqs.size()]),
128             ap);
129   }
130
131   public JalviewStructureDisplayI viewStructures(PDBEntry pdb,
132           SequenceI[] seqsForPdb, AlignmentPanel ap)
133   {
134     return viewStructures(getViewerType(), pdb, seqsForPdb, ap);
135   }
136
137   protected JalviewStructureDisplayI viewStructures(ViewerType viewerType,
138           PDBEntry[] pdbs, SequenceI[][] seqsForPdbs, AlignmentPanel ap)
139   {
140     PDBEntry[] pdbsForFile = getUniquePdbFiles(pdbs);
141     JalviewStructureDisplayI sview = null;
142     if (viewerType.equals(ViewerType.JMOL))
143     {
144       sview = new AppJmol(ap, pdbsForFile,
145               ap.av.collateForPDB(pdbsForFile));
146     }
147     else if (viewerType.equals(ViewerType.CHIMERA))
148     {
149       sview = new ChimeraViewFrame(pdbsForFile,
150               ap.av.collateForPDB(pdbsForFile), ap);
151     }
152     else
153     {
154       Cache.log.error("Unknown structure viewer type "
155               + getViewerType().toString());
156     }
157     return sview;
158   }
159
160   /**
161    * Convert the array of PDBEntry into an array with no filename repeated
162    * 
163    * @param pdbs
164    * @return
165    */
166   static PDBEntry[] getUniquePdbFiles(PDBEntry[] pdbs)
167   {
168     if (pdbs == null)
169     {
170       return null;
171     }
172     List<PDBEntry> uniques = new ArrayList<PDBEntry>();
173     List<String> filesSeen = new ArrayList<String>();
174     for (PDBEntry entry : pdbs)
175     {
176       String file = entry.getFile();
177       if (file == null)
178       {
179         uniques.add(entry);
180       }
181       else if (!filesSeen.contains(file))
182       {
183         uniques.add(entry);
184         filesSeen.add(file);
185       }
186     }
187     return uniques.toArray(new PDBEntry[uniques.size()]);
188   }
189
190   protected JalviewStructureDisplayI viewStructures(ViewerType viewerType,
191           PDBEntry pdb, SequenceI[] seqsForPdb, AlignmentPanel ap)
192   {
193     JalviewStructureDisplayI sview = null;
194     if (viewerType.equals(ViewerType.JMOL))
195     {
196       sview = new AppJmol(pdb, seqsForPdb, null, ap);
197     }
198     else if (viewerType.equals(ViewerType.CHIMERA))
199     {
200       sview = new ChimeraViewFrame(pdb, seqsForPdb, null, ap);
201     }
202     else
203     {
204       Cache.log.error("Unknown structure viewer type "
205               + getViewerType().toString());
206     }
207     return sview;
208   }
209
210   /**
211    * Create a new panel controlling a structure viewer.
212    * 
213    * @param type
214    * @param pdbf
215    * @param id
216    * @param sq
217    * @param alignPanel
218    * @param viewerData
219    * @param fileloc
220    * @param rect
221    * @param vid
222    * @return
223    */
224   public JalviewStructureDisplayI createView(ViewerType type, String[] pdbf,
225           String[] id, SequenceI[][] sq, AlignmentPanel alignPanel,
226           StructureViewerModel viewerData, String fileloc, Rectangle rect,
227           String vid)
228   {
229     final boolean useinViewerSuperpos = viewerData.isAlignWithPanel();
230     final boolean usetoColourbyseq = viewerData.isColourWithAlignPanel();
231     final boolean viewerColouring = viewerData.isColourByViewer();
232
233     JalviewStructureDisplayI sview = null;
234     switch (type)
235     {
236     case JMOL:
237       sview = new AppJmol(pdbf, id, sq, alignPanel, usetoColourbyseq,
238               useinViewerSuperpos, viewerColouring, fileloc, rect, vid);
239       break;
240     case CHIMERA:
241       Cache.log.error(
242               "Unsupported structure viewer type " + type.toString());
243       break;
244     default:
245       Cache.log.error("Unknown structure viewer type " + type.toString());
246     }
247     return sview;
248   }
249
250 }