JAL-2089 patch broken merge to master for Release 2.10.0b1
[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(StructureSelectionManager structureSelectionManager)
65   {
66     ssm = structureSelectionManager;
67   }
68
69   /**
70    * View multiple PDB entries, each with associated sequences
71    * 
72    * @param pdbs
73    * @param seqsForPdbs
74    * @param ap
75    * @return
76    */
77   public JalviewStructureDisplayI viewStructures(PDBEntry[] pdbs,
78           SequenceI[][] seqsForPdbs, AlignmentPanel ap)
79   {
80     JalviewStructureDisplayI viewer = onlyOnePdb(pdbs, seqsForPdbs, ap);
81     if (viewer != null)
82     {
83       return viewer;
84     }
85     return viewStructures(getViewerType(), pdbs, seqsForPdbs, ap);
86   }
87
88   /**
89    * A strictly temporary method pending JAL-1761 refactoring. Determines if all
90    * the passed PDB entries are the same (this is the case if selected sequences
91    * to view structure for are chains of the same structure). If so, calls the
92    * single-pdb version of viewStructures and returns the viewer, else returns
93    * null.
94    * 
95    * @param pdbs
96    * @param seqsForPdbs
97    * @param ap
98    * @return
99    */
100   private JalviewStructureDisplayI onlyOnePdb(PDBEntry[] pdbs,
101           SequenceI[][] seqsForPdbs, AlignmentPanel ap)
102   {
103     List<SequenceI> seqs = new ArrayList<SequenceI>();
104     if (pdbs == null || pdbs.length == 0)
105     {
106       return null;
107     }
108     int i = 0;
109     String firstFile = pdbs[0].getFile();
110     for (PDBEntry pdb : pdbs)
111     {
112       String pdbFile = pdb.getFile();
113       if (pdbFile == null || !pdbFile.equals(firstFile))
114       {
115         return null;
116       }
117       SequenceI[] pdbseqs = seqsForPdbs[i++];
118       if (pdbseqs != null)
119       {
120         for (SequenceI sq : pdbseqs)
121         {
122           seqs.add(sq);
123         }
124       }
125     }
126     return viewStructures(pdbs[0],
127             seqs.toArray(new SequenceI[seqs.size()]), ap);
128   }
129
130   public JalviewStructureDisplayI viewStructures(PDBEntry pdb,
131           SequenceI[] seqsForPdb, AlignmentPanel ap)
132   {
133     return viewStructures(getViewerType(), pdb, seqsForPdb, ap);
134   }
135
136   protected JalviewStructureDisplayI viewStructures(ViewerType viewerType,
137           PDBEntry[] pdbs, SequenceI[][] seqsForPdbs, AlignmentPanel ap)
138   {
139     PDBEntry[] pdbsForFile = getUniquePdbFiles(pdbs);
140     JalviewStructureDisplayI sview = null;
141     if (viewerType.equals(ViewerType.JMOL))
142     {
143       sview = new AppJmol(ap, pdbsForFile, ap.av.collateForPDB(pdbsForFile));
144     }
145     else if (viewerType.equals(ViewerType.CHIMERA))
146     {
147       sview = new ChimeraViewFrame(pdbsForFile,
148               ap.av.collateForPDB(pdbsForFile), ap);
149     }
150     else
151     {
152       Cache.log.error("Unknown structure viewer type "
153               + getViewerType().toString());
154     }
155     return sview;
156   }
157
158   /**
159    * Convert the array of PDBEntry into an array with no filename repeated
160    * 
161    * @param pdbs
162    * @return
163    */
164   static PDBEntry[] getUniquePdbFiles(PDBEntry[] pdbs)
165   {
166     if (pdbs == null)
167     {
168       return null;
169     }
170     List<PDBEntry> uniques = new ArrayList<PDBEntry>();
171     List<String> filesSeen = new ArrayList<String>();
172     for (PDBEntry entry : pdbs)
173     {
174       String file = entry.getFile();
175       if (file == null)
176       {
177         uniques.add(entry);
178       }
179       else if (!filesSeen.contains(file))
180       {
181         uniques.add(entry);
182         filesSeen.add(file);
183       }
184     }
185     return uniques.toArray(new PDBEntry[uniques.size()]);
186   }
187
188   protected JalviewStructureDisplayI viewStructures(ViewerType viewerType,
189           PDBEntry pdb, SequenceI[] seqsForPdb, AlignmentPanel ap)
190   {
191     JalviewStructureDisplayI sview = null;
192     if (viewerType.equals(ViewerType.JMOL))
193     {
194       sview = new AppJmol(pdb, seqsForPdb, null, ap);
195     }
196     else if (viewerType.equals(ViewerType.CHIMERA))
197     {
198       sview = new ChimeraViewFrame(pdb, seqsForPdb, null, ap);
199     }
200     else
201     {
202       Cache.log.error("Unknown structure viewer type "
203               + getViewerType().toString());
204     }
205     return sview;
206   }
207
208   /**
209    * Create a new panel controlling a structure viewer.
210    * 
211    * @param type
212    * @param pdbf
213    * @param id
214    * @param sq
215    * @param alignPanel
216    * @param viewerData
217    * @param fileloc
218    * @param rect
219    * @param vid
220    * @return
221    */
222   public JalviewStructureDisplayI createView(ViewerType type,
223           String[] pdbf, String[] id, SequenceI[][] sq,
224           AlignmentPanel alignPanel, StructureViewerModel viewerData,
225           String fileloc, Rectangle rect, String vid)
226   {
227     final boolean useinViewerSuperpos = viewerData.isAlignWithPanel();
228     final boolean usetoColourbyseq = viewerData.isColourWithAlignPanel();
229     final boolean viewerColouring = viewerData.isColourByViewer();
230
231     JalviewStructureDisplayI sview = null;
232     switch (type)
233     {
234     case JMOL:
235       sview = new AppJmol(pdbf, id, sq, alignPanel, usetoColourbyseq,
236               useinViewerSuperpos, viewerColouring, fileloc, rect, vid);
237       break;
238     case CHIMERA:
239       Cache.log.error("Unsupported structure viewer type "
240               + type.toString());
241       break;
242     default:
243       Cache.log.error("Unknown structure viewer type " + type.toString());
244     }
245     return sview;
246   }
247
248 }