Clover icon

Coverage Report

  1. Project Clover database Mon Sep 2 2024 17:57:51 BST
  2. Package jalview.ext.jmol

File JalviewJmolBinding.java

 

Coverage histogram

../../../img/srcFileCovDistChart6.png
37% of files have more coverage

Code metrics

132
303
49
1
1,142
776
148
0.49
6.18
49
3.02

Classes

Class Line # Actions
JalviewJmolBinding 66 303 148
0.5454545654.5%
 

Contributing tests

This file is covered by 66 tests. .

Source view

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.ext.jmol;
22   
23    import java.awt.Container;
24    import java.awt.event.ComponentEvent;
25    import java.awt.event.ComponentListener;
26    import java.io.File;
27    import java.net.URL;
28    import java.util.ArrayList;
29    import java.util.Arrays;
30    import java.util.HashMap;
31    import java.util.List;
32    import java.util.Map;
33    import java.util.StringTokenizer;
34    import java.util.Vector;
35   
36    import javax.swing.SwingUtilities;
37   
38    import org.jmol.adapter.smarter.SmarterJmolAdapter;
39    import org.jmol.api.JmolAppConsoleInterface;
40    import org.jmol.api.JmolSelectionListener;
41    import org.jmol.api.JmolStatusListener;
42    import org.jmol.api.JmolViewer;
43    import org.jmol.c.CBK;
44    import org.jmol.viewer.Viewer;
45   
46    import jalview.api.AlignmentViewPanel;
47    import jalview.api.FeatureRenderer;
48    import jalview.api.FeatureSettingsModelI;
49    import jalview.api.SequenceRenderer;
50    import jalview.bin.Console;
51    import jalview.datamodel.PDBEntry;
52    import jalview.datamodel.SequenceI;
53    import jalview.gui.AppJmol;
54    import jalview.gui.IProgressIndicator;
55    import jalview.gui.StructureViewer.ViewerType;
56    import jalview.io.DataSourceType;
57    import jalview.io.StructureFile;
58    import jalview.structure.AtomSpec;
59    import jalview.structure.StructureCommand;
60    import jalview.structure.StructureCommandI;
61    import jalview.structure.StructureSelectionManager;
62    import jalview.structures.models.AAStructureBindingModel;
63    import jalview.ws.dbsources.Pdb;
64    import javajs.util.BS;
65   
 
66    public abstract class JalviewJmolBinding extends AAStructureBindingModel
67    implements JmolStatusListener, JmolSelectionListener,
68    ComponentListener
69    {
70    private String lastMessage;
71   
72    /*
73    * when true, try to search the associated datamodel for sequences that are
74    * associated with any unknown structures in the Jmol view.
75    */
76    private boolean associateNewStructs = false;
77   
78    private Vector<String> atomsPicked = new Vector<>();
79   
80    private String lastCommand;
81   
82    private boolean loadedInline;
83   
84    private StringBuffer resetLastRes = new StringBuffer();
85   
86    public Viewer jmolViewer;
87   
 
88  45 toggle public JalviewJmolBinding(StructureSelectionManager ssm,
89    PDBEntry[] pdbentry, SequenceI[][] sequenceIs,
90    DataSourceType protocol)
91    {
92  45 super(ssm, pdbentry, sequenceIs, protocol);
93  45 setStructureCommands(new JmolCommands());
94    /*
95    * viewer = JmolViewer.allocateViewer(renderPanel, new SmarterJmolAdapter(),
96    * "jalviewJmol", ap.av.applet .getDocumentBase(), ap.av.applet.getCodeBase(),
97    * "", this);
98    *
99    * jmolpopup = JmolPopup.newJmolPopup(viewer, true, "Jmol", true);
100    */
101    }
102   
 
103  0 toggle public JalviewJmolBinding(StructureSelectionManager ssm,
104    SequenceI[][] seqs, Viewer theViewer)
105    {
106  0 super(ssm, seqs);
107   
108  0 jmolViewer = theViewer;
109  0 jmolViewer.setJmolStatusListener(this);
110  0 jmolViewer.addSelectionListener(this);
111  0 setStructureCommands(new JmolCommands());
112    }
113   
114    /**
115    * construct a title string for the viewer window based on the data jalview
116    * knows about
117    *
118    * @return
119    */
 
120  45 toggle public String getViewerTitle()
121    {
122  45 return getViewerTitle("Jmol", true);
123    }
124   
 
125  39 toggle private String jmolScript(String script)
126    {
127  39 return jmolScript(script, false);
128    }
129   
 
130  1142 toggle private String jmolScript(String script, boolean useScriptWait)
131    {
132  1142 Console.debug(">>Jmol>> " + script);
133  1143 String s;
134  1143 if (useScriptWait)
135    {
136  2 s = jmolViewer.scriptWait(script);
137    }
138    else
139    {
140  1141 s = jmolViewer.evalStringQuiet(script); // scriptWait(script); BH
141    }
142  1143 Console.debug("<<Jmol<< " + s);
143   
144  1143 return s;
145    }
146   
 
147  446 toggle @Override
148    public List<String> executeCommand(StructureCommandI command,
149    boolean getReply)
150    {
151  446 if (command == null)
152    {
153  0 return null;
154    }
155  446 String cmd = command.getCommand();
156  446 jmolHistory(false);
157  446 if (lastCommand == null || !lastCommand.equals(cmd))
158    {
159  212 jmolScript(cmd + "\n", command.isWaitNeeded());
160    }
161  446 jmolHistory(true);
162  446 lastCommand = cmd;
163  446 return null;
164    }
165   
 
166  0 toggle public void createImage(String file, String type, int quality)
167    {
168  0 jalview.bin.Console.outPrintln("JMOL CREATE IMAGE");
169    }
170   
 
171  4 toggle @Override
172    public String createImage(String fileName, String type,
173    Object textOrBytes, int quality)
174    {
175  4 jalview.bin.Console.outPrintln("JMOL CREATE IMAGE");
176  4 return null;
177    }
178   
 
179  0 toggle @Override
180    public String eval(String strEval)
181    {
182    // jalview.bin.Console.outPrintln(strEval);
183    // "# 'eval' is implemented only for the applet.";
184  0 return null;
185    }
186   
187    // End StructureListener
188    // //////////////////////////
189   
190    ////////////////////////////
191    // HETATM get
192    //
193   
 
194  49 toggle @Override
195    public Map<String, String> getHetatmNames()
196    {
197  49 HashMap<String, String> hetlist = new HashMap();
198  99 for (int mc = 0; mc < jmolViewer.ms.mc; mc++)
199    {
200  50 Map<String, String> hets = jmolViewer.ms.getHeteroList(mc);
201  50 if (hets != null)
202    {
203  10 hetlist.putAll(hets);
204    }
205    }
206  49 return hetlist;
207    }
208    //
209    ////////////////////////////
210   
 
211  0 toggle @Override
212    public float[][] functionXY(String functionName, int x, int y)
213    {
214  0 return null;
215    }
216   
 
217  0 toggle @Override
218    public float[][][] functionXYZ(String functionName, int nx, int ny,
219    int nz)
220    {
221    // TODO Auto-generated method stub
222  0 return null;
223    }
224   
225    /**
226    * map between index of model filename returned from getPdbFile and the first
227    * index of models from this file in the viewer. Note - this is not trimmed -
228    * use getPdbFile to get number of unique models.
229    */
230    private int _modelFileNameMap[];
231   
 
232  1088 toggle @Override
233    public synchronized String[] getStructureFiles()
234    {
235  1088 if (jmolViewer == null)
236    {
237  48 return new String[0];
238    }
239   
240  1040 if (modelFileNames == null)
241    {
242  201 int modelCount = jmolViewer.ms.mc;
243  201 String filePath = null;
244  201 List<String> mset = new ArrayList<>();
245  403 for (int i = 0; i < modelCount; ++i)
246    {
247    /*
248    * defensive check for null as getModelFileName can return null even when model
249    * count ms.mc is > 0
250    */
251  202 filePath = jmolViewer.ms.getModelFileName(i);
252  202 if (filePath != null && !mset.contains(filePath))
253    {
254  65 mset.add(filePath);
255    }
256    }
257  201 if (!mset.isEmpty())
258    {
259  64 modelFileNames = mset.toArray(new String[mset.size()]);
260    }
261    }
262   
263  1040 return modelFileNames;
264    }
265   
266    /**
267    * map from string to applet
268    */
 
269  0 toggle @Override
270    public Map<String, Object> getRegistryInfo()
271    {
272    // TODO Auto-generated method stub
273  0 return null;
274    }
275   
276    // ///////////////////////////////
277    // JmolStatusListener
278   
 
279  0 toggle public void handlePopupMenu(int x, int y)
280    {
281    // jmolpopup.show(x, y);
282    // jmolpopup.jpiShow(x, y);
283    }
284   
285    /**
286    * Highlight zero, one or more atoms on the structure
287    */
 
288  0 toggle @Override
289    public void highlightAtoms(List<AtomSpec> atoms)
290    {
291  0 if (atoms != null)
292    {
293  0 if (resetLastRes.length() > 0)
294    {
295  0 jmolScript(resetLastRes.toString());
296  0 resetLastRes.setLength(0);
297    }
298  0 StringBuilder highlightCommands = null;
299  0 for (AtomSpec atom : atoms)
300    {
301  0 StringBuilder thisAtom = highlightAtom(atom.getAtomIndex(),
302    atom.getPdbResNum(), atom.getChain(), atom.getPdbFile());
303  0 if (thisAtom != null)
304    {
305  0 if (highlightCommands == null)
306    {
307  0 highlightCommands = thisAtom;
308    }
309    else
310    {
311  0 highlightCommands.append(thisAtom);
312    }
313    }
314    }
315  0 if (highlightCommands != null)
316    {
317  0 jmolHistory(false);
318  0 jmolScript(highlightCommands.toString());
319  0 jmolHistory(true);
320    }
321    // Highlight distances between atoms with a 'measure' command - not yet
322    // working
323    // if (atoms.size() >= 2)
324    // {
325    // StringBuilder sb = new StringBuilder();
326    // for (int a = 0; a < atoms.size(); a++)
327    // {
328    // AtomSpec speca = atoms.get(a);
329    // String a_model = getModelIdForFile(speca.getPdbFile());
330    // for (int b = a + 1; b < atoms.size(); b++)
331    // {
332    // AtomSpec specb = atoms.get(b);
333    // String b_model = getModelIdForFile(speca.getPdbFile());
334    // sb.append("measure ALL (" + speca.getAtomIndex() + " and */"
335    // + a_model + ") (" + specb.getAtomIndex() + " and */"
336    // + b_model + ");");
337    // }
338    // }
339    // jmolHistory(false, useScriptWait);
340    // jmolScript(sb.toString(), useScriptWait);
341    // jmolHistory(true, useScriptWait);
342    // }
343   
344    }
345   
346    }
347   
348    // jmol/ssm only
 
349  0 toggle private StringBuilder highlightAtom(int atomIndex, int pdbResNum,
350    String chain, String pdbfile)
351    {
352  0 String modelId = getModelIdForFile(pdbfile);
353  0 if (modelId.isEmpty())
354    {
355  0 return null;
356    }
357   
358  0 StringBuilder selection = new StringBuilder(32);
359  0 StringBuilder cmd = new StringBuilder(64);
360  0 selection.append("select ").append(String.valueOf(pdbResNum));
361  0 selection.append(":");
362  0 if (!chain.equals(" "))
363    {
364  0 selection.append(chain);
365    }
366  0 selection.append(" /").append(modelId);
367   
368  0 cmd.append(selection).append(";wireframe 100;").append(selection)
369    .append(" and not hetero;").append("spacefill 200;select none");
370   
371  0 resetLastRes.append(selection).append(";wireframe 0;").append(selection)
372    .append(" and not hetero; spacefill 0;");
373   
374  0 return cmd;
375    }
376   
377    private boolean debug = true;
378   
 
379  892 toggle private void jmolHistory(boolean enable)
380    {
381  892 jmolHistory(enable, false);
382    }
383   
 
384  892 toggle private void jmolHistory(boolean enable, boolean useScriptWait)
385    {
386  892 jmolScript("History " + ((debug || enable) ? "on" : "off"),
387    useScriptWait);
388    }
389   
 
390  0 toggle public void loadInline(String string)
391    {
392  0 loadedInline = true;
393    // TODO: re JAL-623
394    // viewer.loadInline(strModel, isAppend);
395    // could do this:
396    // construct fake fullPathName and fileName so we can identify the file
397    // later.
398    // Then, construct pass a reader for the string to Jmol.
399    // ((org.jmol.Viewer.Viewer) viewer).loadModelFromFile(fullPathName,
400    // fileName, null, reader, false, null, null, 0);
401  0 jmolViewer.openStringInline(string);
402    }
403   
 
404  1 toggle protected void mouseOverStructure(int atomIndex, final String strInfo)
405    {
406  1 int pdbResNum;
407  1 int alocsep = strInfo.indexOf("^");
408  1 int mdlSep = strInfo.indexOf("/");
409  1 int chainSeparator = strInfo.indexOf(":"), chainSeparator1 = -1;
410   
411  1 if (chainSeparator == -1)
412    {
413  0 chainSeparator = strInfo.indexOf(".");
414  0 if (mdlSep > -1 && mdlSep < chainSeparator)
415    {
416  0 chainSeparator1 = chainSeparator;
417  0 chainSeparator = mdlSep;
418    }
419    }
420    // handle insertion codes
421  1 if (alocsep != -1)
422    {
423  0 pdbResNum = Integer.parseInt(
424    strInfo.substring(strInfo.indexOf("]") + 1, alocsep));
425   
426    }
427    else
428    {
429  1 pdbResNum = Integer.parseInt(
430    strInfo.substring(strInfo.indexOf("]") + 1, chainSeparator));
431    }
432  1 String chainId;
433   
434  1 if (strInfo.indexOf(":") > -1)
435    {
436  1 chainId = strInfo.substring(strInfo.indexOf(":") + 1,
437    strInfo.indexOf("."));
438    }
439    else
440    {
441  0 chainId = " ";
442    }
443   
444  1 String pdbfilename = modelFileNames[0]; // default is first model
445  1 if (mdlSep > -1)
446    {
447  1 if (chainSeparator1 == -1)
448    {
449  1 chainSeparator1 = strInfo.indexOf(".", mdlSep);
450    }
451  1 String mdlId = (chainSeparator1 > -1)
452    ? strInfo.substring(mdlSep + 1, chainSeparator1)
453    : strInfo.substring(mdlSep + 1);
454  1 try
455    {
456    // recover PDB filename for the model hovered over.
457  1 int mnumber = Integer.valueOf(mdlId).intValue() - 1;
458  1 if (_modelFileNameMap != null)
459    {
460  0 int _mp = _modelFileNameMap.length - 1;
461   
462  0 while (mnumber < _modelFileNameMap[_mp])
463    {
464  0 _mp--;
465    }
466  0 pdbfilename = modelFileNames[_mp];
467    }
468    else
469    {
470  1 if (mnumber >= 0 && mnumber < modelFileNames.length)
471    {
472  1 pdbfilename = modelFileNames[mnumber];
473    }
474   
475  1 if (pdbfilename == null)
476    {
477  0 pdbfilename = new File(jmolViewer.ms.getModelFileName(mnumber))
478    .getAbsolutePath();
479    }
480    }
481    } catch (Exception e)
482    {
483    }
484    }
485   
486    /*
487    * highlight position on alignment(s); if some text is returned, show this as a
488    * second line on the structure hover tooltip
489    */
490  1 String label = getSsm().mouseOverStructure(pdbResNum, chainId,
491    pdbfilename);
492  1 if (label != null)
493    {
494    // change comma to pipe separator (newline token for Jmol)
495  0 label = label.replace(',', '|');
496  0 StringTokenizer toks = new StringTokenizer(strInfo, " ");
497  0 StringBuilder sb = new StringBuilder();
498  0 sb.append("select ").append(String.valueOf(pdbResNum)).append(":")
499    .append(chainId).append("/1");
500  0 sb.append(";set hoverLabel \"").append(toks.nextToken()).append(" ")
501    .append(toks.nextToken());
502  0 sb.append("|").append(label).append("\"");
503  0 executeCommand(new StructureCommand(sb.toString()), false);
504    }
505    }
506   
 
507  0 toggle public void notifyAtomHovered(int atomIndex, String strInfo, String data)
508    {
509  0 if (strInfo.equals(lastMessage))
510    {
511  0 return;
512    }
513  0 lastMessage = strInfo;
514  0 if (data != null)
515    {
516  0 jalview.bin.Console.errPrintln(
517    "Ignoring additional hover info: " + data + " (other info: '"
518    + strInfo + "' pos " + atomIndex + ")");
519    }
520  0 mouseOverStructure(atomIndex, strInfo);
521    }
522   
523    /*
524    * { if (history != null && strStatus != null &&
525    * !strStatus.equals("Script completed")) { history.append("\n" + strStatus); }
526    * }
527    */
528   
 
529  0 toggle public void notifyAtomPicked(int atomIndex, String strInfo,
530    String strData)
531    {
532    /**
533    * this implements the toggle label behaviour copied from the original
534    * structure viewer, mc_view
535    */
536  0 if (strData != null)
537    {
538  0 jalview.bin.Console.errPrintln(
539    "Ignoring additional pick data string " + strData);
540    }
541  0 int chainSeparator = strInfo.indexOf(":");
542  0 int p = 0;
543  0 if (chainSeparator == -1)
544    {
545  0 chainSeparator = strInfo.indexOf(".");
546    }
547   
548  0 String picked = strInfo.substring(strInfo.indexOf("]") + 1,
549    chainSeparator);
550  0 String mdlString = "";
551  0 if ((p = strInfo.indexOf(":")) > -1)
552    {
553  0 picked += strInfo.substring(p, strInfo.indexOf("."));
554    }
555   
556  0 if ((p = strInfo.indexOf("/")) > -1)
557    {
558  0 mdlString += strInfo.substring(p, strInfo.indexOf(" #"));
559    }
560  0 picked = "((" + picked + ".CA" + mdlString + ")|(" + picked + ".P"
561    + mdlString + "))";
562  0 jmolHistory(false);
563   
564  0 if (!atomsPicked.contains(picked))
565    {
566  0 jmolScript("select " + picked + ";label %n %r:%c");
567  0 atomsPicked.addElement(picked);
568    }
569    else
570    {
571  0 jmolViewer.evalString("select " + picked + ";label off");
572  0 atomsPicked.removeElement(picked);
573    }
574  0 jmolHistory(true);
575    // TODO: in application this happens
576    //
577    // if (scriptWindow != null)
578    // {
579    // scriptWindow.sendConsoleMessage(strInfo);
580    // scriptWindow.sendConsoleMessage("\n");
581    // }
582   
583    }
584   
 
585  159 toggle @Override
586    public void notifyCallback(CBK type, Object[] data)
587    {
588    /*
589    * ensure processed in AWT thread to avoid risk of deadlocks
590    */
591  159 SwingUtilities.invokeLater(new Runnable()
592    {
593   
 
594  159 toggle @Override
595    public void run()
596    {
597  159 processCallback(type, data);
598    }
599    });
600    }
601   
602    /**
603    * Processes one callback notification from Jmol
604    *
605    * @param type
606    * @param data
607    */
 
608  159 toggle protected void processCallback(CBK type, Object[] data)
609    {
610  159 try
611    {
612  159 switch (type)
613    {
614  60 case LOADSTRUCT:
615  60 notifyFileLoaded((String) data[1], (String) data[2],
616    (String) data[3], (String) data[4],
617    ((Integer) data[5]).intValue());
618   
619  59 break;
620  0 case PICK:
621  0 notifyAtomPicked(((Integer) data[2]).intValue(), (String) data[1],
622    (String) data[0]);
623    // also highlight in alignment
624    // deliberate fall through
625  0 case HOVER:
626  0 notifyAtomHovered(((Integer) data[2]).intValue(), (String) data[1],
627    (String) data[0]);
628  0 break;
629  8 case SCRIPT:
630  8 notifyScriptTermination((String) data[2],
631    ((Integer) data[3]).intValue());
632  8 break;
633  32 case ECHO:
634  32 sendConsoleEcho((String) data[1]);
635  32 break;
636  0 case MESSAGE:
637  0 sendConsoleMessage(
638  0 (data == null) ? ((String) null) : (String) data[1]);
639  0 break;
640  0 case ERROR:
641    // jalview.bin.Console.errPrintln("Ignoring error callback.");
642  0 break;
643  52 case SYNC:
644  0 case RESIZE:
645  52 refreshGUI();
646  52 break;
647  7 case MEASURE:
648   
649  0 case CLICK:
650  0 default:
651  7 jalview.bin.Console.errPrintln(
652    "Unhandled callback " + type + " " + data[1].toString());
653  7 break;
654    }
655    } catch (Exception e)
656    {
657  1 jalview.bin.Console
658    .errPrintln("Squashed Jmol callback handler error:");
659  1 e.printStackTrace();
660    }
661    }
662   
 
663  360 toggle @Override
664    public boolean notifyEnabled(CBK callbackPick)
665    {
666  360 switch (callbackPick)
667    {
668  32 case ECHO:
669  60 case LOADSTRUCT:
670  7 case MEASURE:
671  0 case MESSAGE:
672  0 case PICK:
673  8 case SCRIPT:
674  0 case HOVER:
675  0 case ERROR:
676  107 return true;
677  253 default:
678  253 return false;
679    }
680    }
681   
682    // incremented every time a load notification is successfully handled -
683    // lightweight mechanism for other threads to detect when they can start
684    // referrring to new structures.
685    private long loadNotifiesHandled = 0;
686   
 
687  60 toggle public long getLoadNotifiesHandled()
688    {
689  60 return loadNotifiesHandled;
690    }
691   
 
692  60 toggle public void notifyFileLoaded(String fullPathName, String fileName2,
693    String modelName, String errorMsg, int modelParts)
694    {
695  60 if (errorMsg != null)
696    {
697  7 fileLoadingError = errorMsg;
698  7 refreshGUI();
699  7 return;
700    }
701    // TODO: deal sensibly with models loaded inLine:
702    // modelName will be null, as will fullPathName.
703   
704    // the rest of this routine ignores the arguments, and simply interrogates
705    // the Jmol view to find out what structures it contains, and adds them to
706    // the structure selection manager.
707  53 fileLoadingError = null;
708  53 String[] oldmodels = modelFileNames;
709  53 modelFileNames = null;
710  53 boolean notifyLoaded = false;
711  53 String[] modelfilenames = getStructureFiles();
712  53 if (modelfilenames == null)
713    {
714    // Jmol is still loading files!
715  7 return;
716    }
717    // first check if we've lost any structures
718  46 if (oldmodels != null && oldmodels.length > 0)
719    {
720  19 int oldm = 0;
721  38 for (int i = 0; i < oldmodels.length; i++)
722    {
723  19 for (int n = 0; n < modelfilenames.length; n++)
724    {
725  19 if (modelfilenames[n] == oldmodels[i])
726    {
727  19 oldmodels[i] = null;
728  19 break;
729    }
730    }
731  19 if (oldmodels[i] != null)
732    {
733  0 oldm++;
734    }
735    }
736  19 if (oldm > 0)
737    {
738  0 String[] oldmfn = new String[oldm];
739  0 oldm = 0;
740  0 for (int i = 0; i < oldmodels.length; i++)
741    {
742  0 if (oldmodels[i] != null)
743    {
744  0 oldmfn[oldm++] = oldmodels[i];
745    }
746    }
747    // deregister the Jmol instance for these structures - we'll add
748    // ourselves again at the end for the current structure set.
749  0 getSsm().removeStructureViewerListener(this, oldmfn);
750    }
751    }
752  46 refreshPdbEntries();
753  93 for (int modelnum = 0; modelnum < modelfilenames.length; modelnum++)
754    {
755  47 String fileName = modelfilenames[modelnum];
756  47 boolean foundEntry = false;
757  47 StructureFile pdb = null;
758  47 String pdbfile = null;
759    // model was probably loaded inline - so check the pdb file hashcode
760  47 if (loadedInline)
761    {
762    // calculate essential attributes for the pdb data imported inline.
763    // prolly need to resolve modelnumber properly - for now just use our
764    // 'best guess'
765  0 pdbfile = jmolViewer.getData(
766    "" + (1 + _modelFileNameMap[modelnum]) + ".0", "PDB");
767    }
768    // search pdbentries and sequences to find correct pdbentry for this
769    // model
770  96 for (int pe = 0; pe < getPdbCount(); pe++)
771    {
772  49 boolean matches = false;
773  49 addSequence(pe, getSequence()[pe]);
774  49 if (fileName == null)
775    {
776  0 if (false)
777    // see JAL-623 - need method of matching pasted data up
778    {
779  0 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
780    pdbfile, DataSourceType.PASTE, getIProgressIndicator());
781  0 getPdbEntry(modelnum).setFile("INLINE" + pdb.getId());
782  0 matches = true;
783  0 foundEntry = true;
784    }
785    }
786    else
787    {
788  49 File fl = new File(getPdbEntry(pe).getFile());
789  49 matches = fl.equals(new File(fileName));
790  49 if (matches)
791    {
792  44 foundEntry = true;
793    // TODO: Jmol can in principle retrieve from CLASSLOADER but
794    // this
795    // needs
796    // to be tested. See mantis bug
797    // https://mantis.lifesci.dundee.ac.uk/view.php?id=36605
798  44 DataSourceType protocol = DataSourceType.URL;
799  44 try
800    {
801  44 if (fl.exists())
802    {
803  44 protocol = DataSourceType.FILE;
804    }
805    } catch (Exception e)
806    {
807    } catch (Error e)
808    {
809    }
810    // Explicitly map to the filename used by Jmol ;
811  44 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
812    fileName, protocol, getIProgressIndicator());
813    // pdbentry[pe].getFile(), protocol);
814   
815    }
816    }
817  49 if (matches)
818    {
819  44 stashFoundChains(pdb, fileName);
820  44 notifyLoaded = true;
821    }
822    }
823   
824  47 if (!foundEntry && associateNewStructs)
825    {
826    // this is a foreign pdb file that jalview doesn't know about - add
827    // it to the dataset and try to find a home - either on a matching
828    // sequence or as a new sequence.
829  0 String pdbcontent = jmolViewer.getData("/" + (modelnum + 1) + ".1",
830    "PDB");
831    // parse pdb file into a chain, etc.
832    // locate best match for pdb in associated views and add mapping to
833    // ssm
834    // if properly registered then
835  0 notifyLoaded = true;
836   
837    }
838    }
839    // FILE LOADED OK
840    // so finally, update the jmol bits and pieces
841    // if (jmolpopup != null)
842    // {
843    // // potential for deadlock here:
844    // // jmolpopup.updateComputedMenus();
845    // }
846  46 if (!isLoadingFromArchive())
847    {
848  39 jmolScript(
849    "model *; select backbone;restrict;cartoon;wireframe off;spacefill off");
850    }
851    // register ourselves as a listener and notify the gui that it needs to
852    // update itself.
853  46 getSsm().addStructureViewerListener(this);
854  46 if (notifyLoaded)
855    {
856  43 FeatureRenderer fr = getFeatureRenderer(null);
857  42 if (fr != null)
858    {
859  42 FeatureSettingsModelI colours = new Pdb().getFeatureColourScheme();
860  42 ((AppJmol) getViewer()).getAlignmentPanel().av
861    .applyFeaturesStyle(colours);
862    }
863  42 refreshGUI();
864  42 loadNotifiesHandled++;
865    }
866  45 setLoadingFromArchive(false);
867    }
868   
 
869  44 toggle protected IProgressIndicator getIProgressIndicator()
870    {
871  44 return null;
872    }
873   
 
874  0 toggle public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
875    {
876  0 notifyAtomPicked(iatom, strMeasure, null);
877    }
878   
879    public abstract void notifyScriptTermination(String strStatus,
880    int msWalltime);
881   
882    /**
883    * display a message echoed from the jmol viewer
884    *
885    * @param strEcho
886    */
887    public abstract void sendConsoleEcho(String strEcho); /*
888    * { showConsole(true);
889    *
890    * history.append("\n" + strEcho); }
891    */
892   
893    // /End JmolStatusListener
894    // /////////////////////////////
895   
896    /**
897    * @param strStatus
898    * status message - usually the response received after a script
899    * executed
900    */
901    public abstract void sendConsoleMessage(String strStatus);
902   
 
903  0 toggle @Override
904    public void setCallbackFunction(String callbackType,
905    String callbackFunction)
906    {
907  0 jalview.bin.Console
908    .errPrintln("Ignoring set-callback request to associate "
909    + callbackType + " with function " + callbackFunction);
910   
911    }
912   
 
913  0 toggle public void showHelp()
914    {
915  0 showUrl("http://wiki.jmol.org"
916    // BH 2018 "http://jmol.sourceforge.net/docs/JmolUserGuide/"
917    , "jmolHelp");
918    }
919   
920    /**
921    * open the URL somehow
922    *
923    * @param target
924    */
925    public abstract void showUrl(String url, String target);
926   
927    /**
928    * called to show or hide the associated console window container.
929    *
930    * @param show
931    */
932    public abstract void showConsole(boolean show);
933   
 
934  175 toggle public static Viewer getJmolData(JmolParser jmolParser)
935    {
936  175 return (Viewer) JmolViewer.allocateViewer(null, null, null, null, null,
937    "-x -o -n", jmolParser);
938    }
939   
940    /**
941    *
942    *
943    *
944    * @param renderPanel
945    * @param jmolfileio
946    * - when true will initialise jmol's file IO system (should be false
947    * in applet context)
948    * @param htmlName
949    * @param documentBase
950    * @param codeBase
951    * @param commandOptions
952    */
 
953  0 toggle public void allocateViewer(Container renderPanel, boolean jmolfileio,
954    String htmlName, URL documentBase, URL codeBase,
955    String commandOptions)
956    {
957  0 allocateViewer(renderPanel, jmolfileio, htmlName, documentBase,
958    codeBase, commandOptions, null, null);
959    }
960   
961    /**
962    *
963    * @param renderPanel
964    * @param jmolfileio
965    * - when true will initialise jmol's file IO system (should be false
966    * in applet context)
967    * @param htmlName
968    * @param documentBase
969    * @param codeBase
970    * @param commandOptions
971    * @param consolePanel
972    * - panel to contain Jmol console
973    * @param buttonsToShow
974    * - buttons to show on the console, in order
975    */
 
976  45 toggle public void allocateViewer(Container renderPanel, boolean jmolfileio,
977    String htmlName, URL documentBase, URL codeBase,
978    String commandOptions, final Container consolePanel,
979    String buttonsToShow)
980    {
981   
982  45 jalview.bin.Console
983    .errPrintln("Allocating Jmol Viewer: " + commandOptions);
984   
985  45 if (commandOptions == null)
986    {
987  0 commandOptions = "";
988    }
989  45 jmolViewer = (Viewer) JmolViewer.allocateViewer(renderPanel,
990  45 (jmolfileio ? new SmarterJmolAdapter() : null),
991    htmlName + ((Object) this).toString(), documentBase, codeBase,
992    commandOptions, this);
993   
994  45 jmolViewer.setJmolStatusListener(this); // extends JmolCallbackListener
995   
996  45 try
997    {
998  45 console = createJmolConsole(consolePanel, buttonsToShow);
999    } catch (Throwable e)
1000    {
1001  0 jalview.bin.Console
1002    .errPrintln("Could not create Jmol application console. "
1003    + e.getMessage());
1004  0 e.printStackTrace();
1005    }
1006  45 if (consolePanel != null)
1007    {
1008  45 consolePanel.addComponentListener(this);
1009   
1010    }
1011   
1012    }
1013   
1014    protected abstract JmolAppConsoleInterface createJmolConsole(
1015    Container consolePanel, String buttonsToShow);
1016   
1017    // BH 2018 -- Jmol console is not working due to problems with styled
1018    // documents.
1019   
1020    protected org.jmol.api.JmolAppConsoleInterface console = null;
1021   
 
1022  0 toggle @Override
1023    public int[] resizeInnerPanel(String data)
1024    {
1025    // Jalview doesn't honour resize panel requests
1026  0 return null;
1027    }
1028   
1029    /**
1030    *
1031    */
 
1032  23 toggle protected void closeConsole()
1033    {
1034  23 if (console != null)
1035    {
1036  23 try
1037    {
1038  23 console.setVisible(false);
1039    } catch (Error e)
1040    {
1041    } catch (Exception x)
1042    {
1043    }
1044  23 ;
1045  23 console = null;
1046    }
1047    }
1048   
1049    /**
1050    * ComponentListener method
1051    */
 
1052  0 toggle @Override
1053    public void componentMoved(ComponentEvent e)
1054    {
1055    }
1056   
1057    /**
1058    * ComponentListener method
1059    */
 
1060  0 toggle @Override
1061    public void componentResized(ComponentEvent e)
1062    {
1063    }
1064   
1065    /**
1066    * ComponentListener method
1067    */
 
1068  0 toggle @Override
1069    public void componentShown(ComponentEvent e)
1070    {
1071  0 showConsole(true);
1072    }
1073   
1074    /**
1075    * ComponentListener method
1076    */
 
1077  0 toggle @Override
1078    public void componentHidden(ComponentEvent e)
1079    {
1080  0 showConsole(false);
1081    }
1082   
 
1083  309 toggle @Override
1084    protected String getModelIdForFile(String pdbFile)
1085    {
1086  309 if (modelFileNames == null)
1087    {
1088  0 return "";
1089    }
1090  313 for (int i = 0; i < modelFileNames.length; i++)
1091    {
1092  312 if (modelFileNames[i].equalsIgnoreCase(pdbFile))
1093    {
1094  308 return String.valueOf(i + 1);
1095    }
1096    }
1097  1 return "";
1098    }
1099   
 
1100  2 toggle @Override
1101    protected ViewerType getViewerType()
1102    {
1103  2 return ViewerType.JMOL;
1104    }
1105   
 
1106  0 toggle @Override
1107    protected String getModelId(int pdbfnum, String file)
1108    {
1109  0 return String.valueOf(pdbfnum + 1);
1110    }
1111   
1112    /**
1113    * Returns ".spt" - the Jmol session file extension
1114    *
1115    * @return
1116    * @see https://chemapps.stolaf.edu/jmol/docs/#writemodel
1117    */
 
1118  2 toggle @Override
1119    public String getSessionFileExtension()
1120    {
1121  2 return ".spt";
1122    }
1123   
 
1124  0 toggle @Override
1125    public void selectionChanged(BS arg0)
1126    {
1127    // TODO Auto-generated method stub
1128   
1129    }
1130   
 
1131  0 toggle @Override
1132    public SequenceRenderer getSequenceRenderer(AlignmentViewPanel avp)
1133    {
1134  0 return new jalview.gui.SequenceRenderer(avp.getAlignViewport());
1135    }
1136   
 
1137  0 toggle @Override
1138    public String getHelpURL()
1139    {
1140  0 return "http://wiki.jmol.org"; // BH 2018
1141    }
1142    }