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