Clover icon

Coverage Report

  1. Project Clover database Thu Nov 7 2024 10:11:34 GMT
  2. Package jalview.ext.jmol

File JalviewJmolBinding.java

 

Coverage histogram

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

Code metrics

136
310
49
1
1,159
792
150
0.48
6.33
49
3.06

Classes

Class Line # Actions
JalviewJmolBinding 66 310 150
0.5393939653.9%
 

Contributing tests

This file is covered by 63 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  40 toggle private String jmolScript(String script)
126    {
127  40 return jmolScript(script, false);
128    }
129   
 
130  1164 toggle private String jmolScript(String script, boolean useScriptWait)
131    {
132  1164 Console.debug(">>Jmol>> " + script);
133  1164 String s;
134  1164 if (useScriptWait)
135    {
136  2 s = jmolViewer.scriptWait(script);
137    }
138    else
139    {
140  1162 s = jmolViewer.evalStringQuiet(script); // scriptWait(script); BH
141    }
142  1164 Console.debug("<<Jmol<< " + s);
143   
144  1164 return s;
145    }
146   
 
147  456 toggle @Override
148    public List<String> executeCommand(StructureCommandI command,
149    boolean getReply)
150    {
151  456 if (command == null)
152    {
153  0 return null;
154    }
155  456 String cmd = command.getCommand();
156  456 jmolHistory(false);
157  456 if (lastCommand == null || !lastCommand.equals(cmd))
158    {
159  212 jmolScript(cmd + "\n", command.isWaitNeeded());
160    }
161  456 jmolHistory(true);
162  456 lastCommand = cmd;
163  456 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  55 toggle @Override
195    public Map<String, String> getHetatmNames()
196    {
197  55 HashMap<String, String> hetlist = new HashMap();
198  111 for (int mc = 0; mc < jmolViewer.ms.mc; mc++)
199    {
200  56 Map<String, String> hets = jmolViewer.ms.getHeteroList(mc);
201  56 if (hets != null)
202    {
203  14 hetlist.putAll(hets);
204    }
205    }
206  55 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  1092 toggle @Override
233    public synchronized String[] getStructureFiles()
234    {
235  1092 if (jmolViewer == null)
236    {
237  46 return new String[0];
238    }
239   
240  1046 if (modelFileNames == null)
241    {
242  194 int modelCount = jmolViewer.ms.mc;
243  194 String filePath = null;
244  194 List<String> mset = new ArrayList<>();
245  389 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  195 filePath = jmolViewer.ms.getModelFileName(i);
252  195 if (filePath != null && !mset.contains(filePath))
253    {
254  67 mset.add(filePath);
255    }
256    }
257  194 if (!mset.isEmpty())
258    {
259  66 modelFileNames = mset.toArray(new String[mset.size()]);
260    }
261    }
262   
263  1046 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  912 toggle private void jmolHistory(boolean enable)
380    {
381  912 jmolHistory(enable, false);
382    }
383   
 
384  912 toggle private void jmolHistory(boolean enable, boolean useScriptWait)
385    {
386  912 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  58 toggle public long getLoadNotifiesHandled()
688    {
689  58 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  6 return;
716    }
717    // first check if we've lost any structures
718  47 if (oldmodels != null && oldmodels.length > 0)
719    {
720  21 int oldm = 0;
721  42 for (int i = 0; i < oldmodels.length; i++)
722    {
723  21 for (int n = 0; n < modelfilenames.length; n++)
724    {
725  21 if (modelfilenames[n] == oldmodels[i])
726    {
727  21 oldmodels[i] = null;
728  21 break;
729    }
730    }
731  21 if (oldmodels[i] != null)
732    {
733  0 oldm++;
734    }
735    }
736  21 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  47 refreshPdbEntries();
753  95 for (int modelnum = 0; modelnum < modelfilenames.length; modelnum++)
754    {
755  48 String fileName = modelfilenames[modelnum];
756  48 boolean foundEntry = false;
757  48 StructureFile pdb = null;
758  48 String pdbfile = null;
759    // model was probably loaded inline - so check the pdb file hashcode
760  48 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  98 for (int pe = 0; pe < getPdbCount(); pe++)
771    {
772  50 boolean matches = false;
773  50 addSequence(pe, getSequence()[pe]);
774  50 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  50 PDBEntry ppe = getPdbEntry(pe);
789  50 if (ppe == null)
790    {
791  0 Console.warn(
792    "Please report under JAL-4440: Unexpected null entry for PDBEntry for a structure (for structure "
793    + fileName + ")");
794   
795  0 continue;
796    }
797  50 if (ppe.getFile() == null)
798    {
799  0 Console.warn(
800    "Please report under JAL-4440: Unexpected null entry for file that we just tried to load into Jmol: pdbEntry: "
801    + ppe.toString() + "(for structure " + fileName
802    + ")");
803  0 continue;
804    }
805  50 File fl = new File(getPdbEntry(pe).getFile());
806  50 matches = fl.equals(new File(fileName));
807  50 if (matches)
808    {
809  45 foundEntry = true;
810    // TODO: Jmol can in principle retrieve from CLASSLOADER but
811    // this
812    // needs
813    // to be tested. See mantis bug
814    // https://mantis.lifesci.dundee.ac.uk/view.php?id=36605
815  45 DataSourceType protocol = DataSourceType.URL;
816  45 try
817    {
818  45 if (fl.exists())
819    {
820  45 protocol = DataSourceType.FILE;
821    }
822    } catch (Exception e)
823    {
824    } catch (Error e)
825    {
826    }
827    // Explicitly map to the filename used by Jmol ;
828  45 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
829    fileName, protocol, getIProgressIndicator());
830    // pdbentry[pe].getFile(), protocol);
831   
832    }
833    }
834  50 if (matches)
835    {
836  45 stashFoundChains(pdb, fileName);
837  45 notifyLoaded = true;
838    }
839    }
840   
841  48 if (!foundEntry && associateNewStructs)
842    {
843    // this is a foreign pdb file that jalview doesn't know about - add
844    // it to the dataset and try to find a home - either on a matching
845    // sequence or as a new sequence.
846  0 String pdbcontent = jmolViewer.getData("/" + (modelnum + 1) + ".1",
847    "PDB");
848    // parse pdb file into a chain, etc.
849    // locate best match for pdb in associated views and add mapping to
850    // ssm
851    // if properly registered then
852  0 notifyLoaded = true;
853   
854    }
855    }
856    // FILE LOADED OK
857    // so finally, update the jmol bits and pieces
858    // if (jmolpopup != null)
859    // {
860    // // potential for deadlock here:
861    // // jmolpopup.updateComputedMenus();
862    // }
863  47 if (!isLoadingFromArchive())
864    {
865  40 jmolScript(
866    "model *; select backbone;restrict;cartoon;wireframe off;spacefill off");
867    }
868    // register ourselves as a listener and notify the gui that it needs to
869    // update itself.
870  47 getSsm().addStructureViewerListener(this);
871  47 if (notifyLoaded)
872    {
873  44 FeatureRenderer fr = getFeatureRenderer(null);
874  43 if (fr != null)
875    {
876  43 FeatureSettingsModelI colours = new Pdb().getFeatureColourScheme();
877  43 ((AppJmol) getViewer()).getAlignmentPanel().av
878    .applyFeaturesStyle(colours);
879    }
880  43 refreshGUI();
881  43 loadNotifiesHandled++;
882    }
883  46 setLoadingFromArchive(false);
884    }
885   
 
886  45 toggle protected IProgressIndicator getIProgressIndicator()
887    {
888  45 return null;
889    }
890   
 
891  0 toggle public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
892    {
893  0 notifyAtomPicked(iatom, strMeasure, null);
894    }
895   
896    public abstract void notifyScriptTermination(String strStatus,
897    int msWalltime);
898   
899    /**
900    * display a message echoed from the jmol viewer
901    *
902    * @param strEcho
903    */
904    public abstract void sendConsoleEcho(String strEcho); /*
905    * { showConsole(true);
906    *
907    * history.append("\n" + strEcho); }
908    */
909   
910    // /End JmolStatusListener
911    // /////////////////////////////
912   
913    /**
914    * @param strStatus
915    * status message - usually the response received after a script
916    * executed
917    */
918    public abstract void sendConsoleMessage(String strStatus);
919   
 
920  0 toggle @Override
921    public void setCallbackFunction(String callbackType,
922    String callbackFunction)
923    {
924  0 jalview.bin.Console
925    .errPrintln("Ignoring set-callback request to associate "
926    + callbackType + " with function " + callbackFunction);
927   
928    }
929   
 
930  0 toggle public void showHelp()
931    {
932  0 showUrl("http://wiki.jmol.org"
933    // BH 2018 "http://jmol.sourceforge.net/docs/JmolUserGuide/"
934    , "jmolHelp");
935    }
936   
937    /**
938    * open the URL somehow
939    *
940    * @param target
941    */
942    public abstract void showUrl(String url, String target);
943   
944    /**
945    * called to show or hide the associated console window container.
946    *
947    * @param show
948    */
949    public abstract void showConsole(boolean show);
950   
 
951  176 toggle public static Viewer getJmolData(JmolParser jmolParser)
952    {
953  176 return (Viewer) JmolViewer.allocateViewer(null, null, null, null, null,
954    "-x -o -n", jmolParser);
955    }
956   
957    /**
958    *
959    *
960    *
961    * @param renderPanel
962    * @param jmolfileio
963    * - when true will initialise jmol's file IO system (should be false
964    * in applet context)
965    * @param htmlName
966    * @param documentBase
967    * @param codeBase
968    * @param commandOptions
969    */
 
970  0 toggle public void allocateViewer(Container renderPanel, boolean jmolfileio,
971    String htmlName, URL documentBase, URL codeBase,
972    String commandOptions)
973    {
974  0 allocateViewer(renderPanel, jmolfileio, htmlName, documentBase,
975    codeBase, commandOptions, null, null);
976    }
977   
978    /**
979    *
980    * @param renderPanel
981    * @param jmolfileio
982    * - when true will initialise jmol's file IO system (should be false
983    * in applet context)
984    * @param htmlName
985    * @param documentBase
986    * @param codeBase
987    * @param commandOptions
988    * @param consolePanel
989    * - panel to contain Jmol console
990    * @param buttonsToShow
991    * - buttons to show on the console, in order
992    */
 
993  45 toggle public void allocateViewer(Container renderPanel, boolean jmolfileio,
994    String htmlName, URL documentBase, URL codeBase,
995    String commandOptions, final Container consolePanel,
996    String buttonsToShow)
997    {
998   
999  45 jalview.bin.Console
1000    .errPrintln("Allocating Jmol Viewer: " + commandOptions);
1001   
1002  45 if (commandOptions == null)
1003    {
1004  0 commandOptions = "";
1005    }
1006  45 jmolViewer = (Viewer) JmolViewer.allocateViewer(renderPanel,
1007  45 (jmolfileio ? new SmarterJmolAdapter() : null),
1008    htmlName + ((Object) this).toString(), documentBase, codeBase,
1009    commandOptions, this);
1010   
1011  45 jmolViewer.setJmolStatusListener(this); // extends JmolCallbackListener
1012   
1013  45 try
1014    {
1015  45 console = createJmolConsole(consolePanel, buttonsToShow);
1016    } catch (Throwable e)
1017    {
1018  0 jalview.bin.Console
1019    .errPrintln("Could not create Jmol application console. "
1020    + e.getMessage());
1021  0 e.printStackTrace();
1022    }
1023  45 if (consolePanel != null)
1024    {
1025  45 consolePanel.addComponentListener(this);
1026   
1027    }
1028   
1029    }
1030   
1031    protected abstract JmolAppConsoleInterface createJmolConsole(
1032    Container consolePanel, String buttonsToShow);
1033   
1034    // BH 2018 -- Jmol console is not working due to problems with styled
1035    // documents.
1036   
1037    protected org.jmol.api.JmolAppConsoleInterface console = null;
1038   
 
1039  0 toggle @Override
1040    public int[] resizeInnerPanel(String data)
1041    {
1042    // Jalview doesn't honour resize panel requests
1043  0 return null;
1044    }
1045   
1046    /**
1047    *
1048    */
 
1049  23 toggle protected void closeConsole()
1050    {
1051  23 if (console != null)
1052    {
1053  23 try
1054    {
1055  23 console.setVisible(false);
1056    } catch (Error e)
1057    {
1058    } catch (Exception x)
1059    {
1060    }
1061  23 ;
1062  23 console = null;
1063    }
1064    }
1065   
1066    /**
1067    * ComponentListener method
1068    */
 
1069  0 toggle @Override
1070    public void componentMoved(ComponentEvent e)
1071    {
1072    }
1073   
1074    /**
1075    * ComponentListener method
1076    */
 
1077  0 toggle @Override
1078    public void componentResized(ComponentEvent e)
1079    {
1080    }
1081   
1082    /**
1083    * ComponentListener method
1084    */
 
1085  0 toggle @Override
1086    public void componentShown(ComponentEvent e)
1087    {
1088  0 showConsole(true);
1089    }
1090   
1091    /**
1092    * ComponentListener method
1093    */
 
1094  0 toggle @Override
1095    public void componentHidden(ComponentEvent e)
1096    {
1097  0 showConsole(false);
1098    }
1099   
 
1100  320 toggle @Override
1101    protected String getModelIdForFile(String pdbFile)
1102    {
1103  320 if (modelFileNames == null)
1104    {
1105  0 return "";
1106    }
1107  323 for (int i = 0; i < modelFileNames.length; i++)
1108    {
1109  323 if (modelFileNames[i].equalsIgnoreCase(pdbFile))
1110    {
1111  320 return String.valueOf(i + 1);
1112    }
1113    }
1114  0 return "";
1115    }
1116   
 
1117  2 toggle @Override
1118    protected ViewerType getViewerType()
1119    {
1120  2 return ViewerType.JMOL;
1121    }
1122   
 
1123  0 toggle @Override
1124    protected String getModelId(int pdbfnum, String file)
1125    {
1126  0 return String.valueOf(pdbfnum + 1);
1127    }
1128   
1129    /**
1130    * Returns ".spt" - the Jmol session file extension
1131    *
1132    * @return
1133    * @see https://chemapps.stolaf.edu/jmol/docs/#writemodel
1134    */
 
1135  2 toggle @Override
1136    public String getSessionFileExtension()
1137    {
1138  2 return ".spt";
1139    }
1140   
 
1141  0 toggle @Override
1142    public void selectionChanged(BS arg0)
1143    {
1144    // TODO Auto-generated method stub
1145   
1146    }
1147   
 
1148  0 toggle @Override
1149    public SequenceRenderer getSequenceRenderer(AlignmentViewPanel avp)
1150    {
1151  0 return new jalview.gui.SequenceRenderer(avp.getAlignViewport());
1152    }
1153   
 
1154  0 toggle @Override
1155    public String getHelpURL()
1156    {
1157  0 return "http://wiki.jmol.org"; // BH 2018
1158    }
1159    }