JAL-1517 fix copyright for 2.8.2
[jalview.git] / src / jalview / ext / jmol / PDBFileWithJmol.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
3  * Copyright (C) 2014 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.ext.jmol;
22
23 import java.io.IOException;
24 import java.util.Hashtable;
25 import java.util.Map;
26
27 import org.jmol.api.JmolStatusListener;
28 import org.jmol.api.JmolViewer;
29 import org.jmol.constant.EnumCallback;
30 import org.jmol.modelset.Group;
31 import org.jmol.modelset.Model;
32 import org.jmol.modelset.ModelSet;
33 import org.jmol.modelset.Polymer;
34 import org.jmol.modelsetbio.BioPolymer;
35 import org.jmol.viewer.Viewer;
36 import org.openscience.jmol.app.JmolApp;
37
38 import jalview.datamodel.AlignmentAnnotation;
39 import jalview.datamodel.Annotation;
40 import jalview.datamodel.PDBEntry;
41 import jalview.datamodel.Sequence;
42 import jalview.datamodel.SequenceI;
43 import jalview.io.AlignFile;
44 import jalview.io.FileParse;
45
46 /**
47  * Import and process PDB files with Jmol
48  * 
49  * @author jprocter
50  * 
51  */
52 public class PDBFileWithJmol extends AlignFile implements
53         JmolStatusListener
54 {
55
56   JmolApp jmolApp = null;
57
58   Viewer viewer = null;
59
60   public PDBFileWithJmol(String inFile, String type)
61           throws IOException
62   {
63     super(inFile, type);
64   }
65   
66
67   public PDBFileWithJmol(FileParse fp) throws IOException
68   {
69     super(fp);
70   }
71
72   public PDBFileWithJmol()
73   {
74     // TODO Auto-generated constructor stub
75   }
76
77   /**
78    * create a headless jmol instance for dataprocessing
79    * 
80    * @return
81    */
82   private Viewer getJmolData()
83   {
84     if (viewer == null)
85     { // note that -o -n -x are all implied
86       jmolApp = new JmolApp();
87       jmolApp.isDataOnly = true;
88       jmolApp.haveConsole = false;
89       jmolApp.haveDisplay = false;
90       jmolApp.exitUponCompletion = true;
91       try
92       {
93         viewer = (Viewer) JmolViewer.allocateViewer(null, null, null, null,
94                 null, jmolApp.commandOptions, this);
95         viewer.setScreenDimension(jmolApp.startupWidth,
96                 jmolApp.startupHeight);
97         jmolApp.startViewer(viewer, null);
98       } catch (ClassCastException x)
99       {
100         throw new Error(
101                 "Jmol version "
102                         + JmolViewer.getJmolVersion()
103                         + " is not compatible with this version of Jalview. Report this problem at issues.jalview.org",
104                 x);
105       }
106     }
107     return viewer;
108   }
109
110   private void waitForScript(Viewer jmd)
111   {
112     while (jmd.isScriptExecuting())
113     {
114       try
115       {
116         Thread.sleep(50);
117
118       } catch (InterruptedException x)
119       {
120       }
121     }
122   }
123
124   /*
125    * (non-Javadoc)
126    * 
127    * @see jalview.io.AlignFile#parse()
128    */
129   @Override
130   public void parse() throws IOException
131   {
132     Viewer jmd = getJmolData();
133     jmd.openReader(getDataName(), getDataName(), getReader());
134     waitForScript(jmd);
135     if (jmd.getModelCount() > 0)
136     {
137       ModelSet ms = jmd.getModelSet();
138       String structs = ms.calculateStructures(null, true, false, true);
139       // System.out.println("Structs\n"+structs);
140       for (Model model : ms.getModels())
141       {
142         for (int _bp = 0, _bpc = model.getBioPolymerCount(); _bp < _bpc; _bp++)
143         {
144           Polymer bp = model.getBioPolymer(_bp);
145           if (bp instanceof BioPolymer)
146           {
147             BioPolymer biopoly = (BioPolymer) bp;
148             char _lastChainId = 0;
149             int[] groups = biopoly.getLeadAtomIndices();
150             Group[] bpgrp = biopoly.getGroups();
151             char seq[] = new char[groups.length], secstr[] = new char[groups.length], secstrcode[] = new char[groups.length];
152             int groupc = 0, len = 0, firstrnum = 1, lastrnum = 0;
153             do
154             {
155               if (groupc >= groups.length
156                       || ms.atoms[groups[groupc]].getChainID() != _lastChainId)
157               {
158                 if (len > 0)
159                 {
160                   char newseq[] = new char[len];
161                   System.arraycopy(seq, 0, newseq, 0, len);
162                   Annotation asecstr[] = new Annotation[len];
163                   for (int p = 0; p < len; p++)
164                   {
165                     if (secstr[p] >= 'A' && secstr[p] <= 'z')
166                     {
167                       asecstr[p] = new Annotation("" + secstr[p], null,
168                               secstrcode[p], Float.NaN);
169                     }
170                   }
171                   SequenceI sq = new Sequence("" + getDataName() + "|"
172                           + model.getModelTitle() + "|" + _lastChainId,
173                           newseq, firstrnum, lastrnum);
174                   PDBEntry pdbe = new PDBEntry();
175                   pdbe.setFile(getDataName());
176                   pdbe.setId(getDataName());
177                   sq.addPDBId(pdbe);
178                   pdbe.setProperty(new Hashtable());
179                   pdbe.getProperty().put("CHAIN",""+_lastChainId);
180                   seqs.add(sq);
181                   if (!(biopoly.isDna() || biopoly.isRna()))
182                   {
183                     AlignmentAnnotation ann = new AlignmentAnnotation(
184                             "Secondary Structure",
185                             "Secondary Structure from PDB File", asecstr);
186                     ann.setCalcId(getClass().getName());
187                     sq.addAlignmentAnnotation(ann);
188                     annotations.add(ann);
189                   }
190                 }
191                 len = 0;
192                 firstrnum = 1;
193                 lastrnum = 0;
194               }
195               if (groupc < groups.length)
196               {
197                 if (len == 0)
198                 {
199                   firstrnum = bpgrp[groupc].getResno();
200                   _lastChainId = bpgrp[groupc].getChainID();
201                 }
202                 else
203                 {
204                   lastrnum = bpgrp[groupc].getResno();
205                 }
206                 seq[len] = bpgrp[groupc].getGroup1();
207                 switch (bpgrp[groupc].getProteinStructureSubType())
208                 {
209                 case HELIX_310:
210                   if (secstr[len] == 0)
211                   {
212                     secstr[len] = '3';
213                   }
214                 case HELIX_ALPHA:
215                   if (secstr[len] == 0)
216                   {
217                     secstr[len] = 'H';
218                   }
219                 case HELIX_PI:
220                   if (secstr[len] == 0)
221                   {
222                     secstr[len] = 'P';
223                   }
224                 case HELIX:
225                   if (secstr[len] == 0)
226                   {
227                     secstr[len] = 'H';
228                   }
229                   secstrcode[len] = 'H';
230                   break;
231                 case SHEET:
232                   secstr[len] = 'E';
233                   secstrcode[len] = 'E';
234                   break;
235                 default:
236                   secstr[len] = 0;
237                   secstrcode[len] = 0;
238                 }
239                 len++;
240               }
241             } while (groupc++ < groups.length);
242
243           }
244         }
245       }
246
247       /*
248        * lastScriptTermination = -9465; String dsspOut =
249        * jmd.evalString("calculate STRUCTURE"); if (dsspOut.equals("pending")) {
250        * while (lastScriptTermination == -9465) { try { Thread.sleep(50); }
251        * catch (Exception x) { } ; } } System.out.println(lastConsoleEcho);
252        */
253     }
254   }
255
256   /*
257    * (non-Javadoc)
258    * 
259    * @see jalview.io.AlignFile#print()
260    */
261   @Override
262   public String print()
263   {
264     // TODO Auto-generated method stub
265     return null;
266   }
267
268   @Override
269   public void setCallbackFunction(String callbackType,
270           String callbackFunction)
271   {
272     // TODO Auto-generated method stub
273
274   }
275
276   /*
277    * @Override public void notifyCallback(EnumCallback type, Object[] data) {
278    * try { switch (type) { case ERROR: case SCRIPT:
279    * notifyScriptTermination((String) data[2], ((Integer) data[3]).intValue());
280    * break; case MESSAGE: sendConsoleMessage((data == null) ? ((String) null) :
281    * (String) data[1]); break; case LOADSTRUCT: notifyFileLoaded((String)
282    * data[1], (String) data[2], (String) data[3], (String) data[4], ((Integer)
283    * data[5]).intValue());
284    * 
285    * break; default: // System.err.println("Unhandled callback " + type + " " //
286    * + data[1].toString()); break; } } catch (Exception e) {
287    * System.err.println("Squashed Jmol callback handler error:");
288    * e.printStackTrace(); } }
289    */
290   public void notifyCallback(EnumCallback type, Object[] data)
291   {
292     String strInfo = (data == null || data[1] == null ? null : data[1]
293             .toString());
294     switch (type)
295     {
296     case ECHO:
297       sendConsoleEcho(strInfo);
298       break;
299     case SCRIPT:
300       notifyScriptTermination((String) data[2],
301               ((Integer) data[3]).intValue());
302       break;
303     case MEASURE:
304       String mystatus = (String) data[3];
305       if (mystatus.indexOf("Picked") >= 0
306               || mystatus.indexOf("Sequence") >= 0) // picking mode
307         sendConsoleMessage(strInfo);
308       else if (mystatus.indexOf("Completed") >= 0)
309         sendConsoleEcho(strInfo.substring(strInfo.lastIndexOf(",") + 2,
310                 strInfo.length() - 1));
311       break;
312     case MESSAGE:
313       sendConsoleMessage(data == null ? null : strInfo);
314       break;
315     case PICK:
316       sendConsoleMessage(strInfo);
317       break;
318     default:
319       break;
320     }
321   }
322
323   private void notifyFileLoaded(String string, String string2,
324           String string3, String string4, int intValue)
325   {
326     // TODO Auto-generated method stub
327
328   }
329
330   String lastConsoleEcho = "";
331
332   private void sendConsoleEcho(String string)
333   {
334     lastConsoleEcho += string;
335     lastConsoleEcho += "\n";
336   }
337
338   String lastConsoleMessage = "";
339
340   private void sendConsoleMessage(String string)
341   {
342     lastConsoleMessage += string;
343     lastConsoleMessage += "\n";
344   }
345
346   int lastScriptTermination = -1;
347
348   String lastScriptMessage = "";
349
350   private void notifyScriptTermination(String string, int intValue)
351   {
352     lastScriptMessage += string;
353     lastScriptMessage += "\n";
354     lastScriptTermination = intValue;
355   }
356
357   @Override
358   public boolean notifyEnabled(EnumCallback callbackPick)
359   {
360     switch (callbackPick)
361     {
362     case MESSAGE:
363     case SCRIPT:
364     case ECHO:
365     case LOADSTRUCT:
366     case ERROR:
367       return true;
368     case MEASURE:
369     case PICK:
370     case HOVER:
371     case RESIZE:
372     case SYNC:
373     case CLICK:
374     case ANIMFRAME:
375     case MINIMIZATION:
376     }
377     return false;
378   }
379
380   @Override
381   public String eval(String strEval)
382   {
383     // TODO Auto-generated method stub
384     return null;
385   }
386
387   @Override
388   public float[][] functionXY(String functionName, int x, int y)
389   {
390     // TODO Auto-generated method stub
391     return null;
392   }
393
394   @Override
395   public float[][][] functionXYZ(String functionName, int nx, int ny, int nz)
396   {
397     // TODO Auto-generated method stub
398     return null;
399   }
400
401   @Override
402   public String createImage(String fileName, String type,
403           Object text_or_bytes, int quality)
404   {
405     // TODO Auto-generated method stub
406     return null;
407   }
408
409   @Override
410   public Map<String, Object> getRegistryInfo()
411   {
412     // TODO Auto-generated method stub
413     return null;
414   }
415
416   @Override
417   public void showUrl(String url)
418   {
419     // TODO Auto-generated method stub
420
421   }
422
423   @Override
424   public void resizeInnerPanel(String data)
425   {
426     // TODO Auto-generated method stub
427
428   }
429
430 }