Clover icon

Coverage Report

  1. Project Clover database Mon Nov 18 2024 09:38:20 GMT
  2. Package jalview.ext.jmol

File JalviewJmolBinding.java

 

Coverage histogram

../../../img/srcFileCovDistChart5.png
33% of files have more coverage

Code metrics

140
316
49
1
1,170
802
152
0.48
6.45
49
3.1

Classes

Class Line # Actions
JalviewJmolBinding 66 316 152
0.4851485248.5%
 

Contributing tests

This file is covered by 24 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  5 toggle public JalviewJmolBinding(StructureSelectionManager ssm,
89    PDBEntry[] pdbentry, SequenceI[][] sequenceIs,
90    DataSourceType protocol)
91    {
92  5 super(ssm, pdbentry, sequenceIs, protocol);
93  5 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  5 toggle public String getViewerTitle()
121    {
122  5 return getViewerTitle("Jmol", true);
123    }
124   
 
125  4 toggle private String jmolScript(String script)
126    {
127  4 return jmolScript(script, false);
128    }
129   
 
130  89 toggle private String jmolScript(String script, boolean useScriptWait)
131    {
132  89 Console.debug(">>Jmol>> " + script);
133  89 String s;
134  89 if (useScriptWait)
135    {
136  0 s = jmolViewer.scriptWait(script);
137    }
138    else
139    {
140  89 s = jmolViewer.evalStringQuiet(script); // scriptWait(script); BH
141    }
142  89 Console.debug("<<Jmol<< " + s);
143   
144  89 return s;
145    }
146   
 
147  30 toggle @Override
148    public List<String> executeCommand(StructureCommandI command,
149    boolean getReply)
150    {
151  30 if (command == null)
152    {
153  0 return null;
154    }
155  30 String cmd = command.getCommand();
156  30 jmolHistory(false);
157  30 if (lastCommand == null || !lastCommand.equals(cmd))
158    {
159  25 jmolScript(cmd + "\n", command.isWaitNeeded());
160    }
161  30 jmolHistory(true);
162  30 lastCommand = cmd;
163  30 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  0 toggle @Override
172    public String createImage(String fileName, String type,
173    Object textOrBytes, int quality)
174    {
175  0 jalview.bin.Console.outPrintln("JMOL CREATE IMAGE");
176  0 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  3 toggle @Override
195    public Map<String, String> getHetatmNames()
196    {
197  3 HashMap<String, String> hetlist = new HashMap();
198  7 for (int mc = 0; mc < jmolViewer.ms.mc; mc++)
199    {
200  4 Map<String, String> hets = jmolViewer.ms.getHeteroList(mc);
201  4 if (hets != null)
202    {
203  1 hetlist.putAll(hets);
204    }
205    }
206  3 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  59 toggle @Override
233    public synchronized String[] getStructureFiles()
234    {
235  59 if (jmolViewer == null)
236    {
237  5 return new String[0];
238    }
239   
240  54 if (modelFileNames == null)
241    {
242  22 int modelCount = jmolViewer.ms.mc;
243  22 String filePath = null;
244  22 List<String> mset = new ArrayList<>();
245  45 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  23 filePath = jmolViewer.ms.getModelFileName(i);
252  23 if (filePath != null && !mset.contains(filePath))
253    {
254  10 mset.add(filePath);
255    }
256    }
257  22 if (!mset.isEmpty())
258    {
259  9 modelFileNames = mset.toArray(new String[mset.size()]);
260    }
261    }
262   
263  54 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  60 toggle private void jmolHistory(boolean enable)
380    {
381  60 jmolHistory(enable, false);
382    }
383   
 
384  60 toggle private void jmolHistory(boolean enable, boolean useScriptWait)
385    {
386  60 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  23 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  23 SwingUtilities.invokeLater(new Runnable()
592    {
593   
 
594  15 toggle @Override
595    public void run()
596    {
597  15 processCallback(type, data);
598    }
599    });
600    }
601   
602    /**
603    * Processes one callback notification from Jmol
604    *
605    * @param type
606    * @param data
607    */
 
608  15 toggle protected void processCallback(CBK type, Object[] data)
609    {
610  15 try
611    {
612  15 switch (type)
613    {
614  4 case LOADSTRUCT:
615  4 notifyFileLoaded((String) data[1], (String) data[2],
616    (String) data[3], (String) data[4],
617    ((Integer) data[5]).intValue());
618   
619  3 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  0 case SCRIPT:
630  0 notifyScriptTermination((String) data[2],
631    ((Integer) data[3]).intValue());
632  0 break;
633  5 case ECHO:
634  5 sendConsoleEcho((String) data[1]);
635  5 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  6 case SYNC:
644  0 case RESIZE:
645  6 refreshGUI();
646  6 break;
647  0 case MEASURE:
648   
649  0 case CLICK:
650  0 default:
651  0 jalview.bin.Console.errPrintln(
652    "Unhandled callback " + type + " " + data[1].toString());
653  0 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  69 toggle @Override
664    public boolean notifyEnabled(CBK callbackPick)
665    {
666  69 switch (callbackPick)
667    {
668  7 case ECHO:
669  6 case LOADSTRUCT:
670  0 case MEASURE:
671  0 case MESSAGE:
672  0 case PICK:
673  0 case SCRIPT:
674  0 case HOVER:
675  0 case ERROR:
676  13 return true;
677  56 default:
678  56 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  24 toggle public long getLoadNotifiesHandled()
688    {
689  24 return loadNotifiesHandled;
690    }
691   
 
692  4 toggle public void notifyFileLoaded(String fullPathName, String fileName2,
693    String modelName, String errorMsg, int modelParts)
694    {
695  4 if (errorMsg != null)
696    {
697  0 fileLoadingError = errorMsg;
698  0 refreshGUI();
699  0 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  4 fileLoadingError = null;
708  4 String[] oldmodels = modelFileNames;
709  4 modelFileNames = null;
710  4 boolean notifyLoaded = false;
711  4 String[] modelfilenames = getStructureFiles();
712  4 if (modelfilenames == null)
713    {
714    // Jmol is still loading files!
715  0 return;
716    }
717  4 if (jalview.bin.Console.isTraceEnabled())
718    {
719  0 jalview.bin.Console.trace("New structures loaded in Jmol:");
720  0 int i=1;
721  0 for (String mfn: modelfilenames)
722    {
723  0 jalview.bin.Console.trace(i++ +" "+((mfn==null) ? "NULL" : mfn));
724    }
725    }
726    // first check if we've lost any structures
727  4 if (oldmodels != null && oldmodels.length > 0)
728    {
729  4 int oldm = 0;
730  8 for (int i = 0; i < oldmodels.length; i++)
731    {
732  4 for (int n = 0; n < modelfilenames.length; n++)
733    {
734  4 if (modelfilenames[n] == oldmodels[i])
735    {
736  4 oldmodels[i] = null;
737  4 break;
738    }
739    }
740  4 if (oldmodels[i] != null)
741    {
742  0 oldm++;
743    }
744    }
745  4 if (oldm > 0)
746    {
747  0 String[] oldmfn = new String[oldm];
748  0 oldm = 0;
749  0 for (int i = 0; i < oldmodels.length; i++)
750    {
751  0 if (oldmodels[i] != null)
752    {
753  0 oldmfn[oldm++] = oldmodels[i];
754    }
755    }
756    // deregister the Jmol instance for these structures - we'll add
757    // ourselves again at the end for the current structure set.
758  0 getSsm().removeStructureViewerListener(this, oldmfn);
759    }
760    }
761  4 refreshPdbEntries();
762  9 for (int modelnum = 0; modelnum < modelfilenames.length; modelnum++)
763    {
764  5 String fileName = modelfilenames[modelnum];
765  5 boolean foundEntry = false;
766  5 StructureFile pdb = null;
767  5 String pdbfile = null;
768    // model was probably loaded inline - so check the pdb file hashcode
769  5 if (loadedInline)
770    {
771    // calculate essential attributes for the pdb data imported inline.
772    // prolly need to resolve modelnumber properly - for now just use our
773    // 'best guess'
774  0 pdbfile = jmolViewer.getData(
775    "" + (1 + _modelFileNameMap[modelnum]) + ".0", "PDB");
776    }
777    // search pdbentries and sequences to find correct pdbentry for this
778    // model
779  12 for (int pe = 0; pe < getPdbCount(); pe++)
780    {
781  7 boolean matches = false;
782  7 addSequence(pe, getSequence()[pe]);
783  7 if (fileName == null)
784    {
785  0 if (false)
786    // see JAL-623 - need method of matching pasted data up
787    {
788  0 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
789    pdbfile, DataSourceType.PASTE, getIProgressIndicator());
790  0 getPdbEntry(modelnum).setFile("INLINE" + pdb.getId());
791  0 matches = true;
792  0 foundEntry = true;
793    }
794    }
795    else
796    {
797  7 PDBEntry ppe = getPdbEntry(pe);
798  7 if (ppe == null)
799    {
800  0 Console.warn(
801    "Please report under JAL-4440: Unexpected null entry for PDBEntry for a structure (for structure "
802    + fileName + ")");
803   
804  0 continue;
805    }
806  7 if (ppe.getFile() == null)
807    {
808  0 Console.warn(
809    "Please report under JAL-4440: Unexpected null entry for file that we just tried to load into Jmol: pdbEntry: "
810    + ppe.toString() + "(for structure " + fileName
811    + ")");
812  0 continue;
813    }
814  7 String jvPdbFile = getPdbEntry(pe).getFile();
815  7 File fl = new File(jvPdbFile);
816  7 matches = fl.equals(new File(fileName)) || JmolCommands.filePathMatch(fileName, jvPdbFile);
817  7 if (matches)
818    {
819  4 foundEntry = true;
820    // TODO: Jmol can in principle retrieve from CLASSLOADER but
821    // this
822    // needs
823    // to be tested. See mantis bug
824    // https://mantis.lifesci.dundee.ac.uk/view.php?id=36605
825  4 DataSourceType protocol = DataSourceType.URL;
826  4 try
827    {
828  4 if (fl.exists())
829    {
830  4 protocol = DataSourceType.FILE;
831    }
832    } catch (Exception e)
833    {
834    } catch (Error e)
835    {
836    }
837    // Explicitly map to the filename used by Jmol ;
838  4 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
839    fileName, protocol, getIProgressIndicator());
840    // pdbentry[pe].getFile(), protocol);
841   
842    }
843    }
844  7 if (matches)
845    {
846  4 stashFoundChains(pdb, fileName);
847  4 notifyLoaded = true;
848    }
849    }
850   
851  5 if (!foundEntry && associateNewStructs)
852    {
853    // this is a foreign pdb file that jalview doesn't know about - add
854    // it to the dataset and try to find a home - either on a matching
855    // sequence or as a new sequence.
856  0 String pdbcontent = jmolViewer.getData("/" + (modelnum + 1) + ".1",
857    "PDB");
858    // parse pdb file into a chain, etc.
859    // locate best match for pdb in associated views and add mapping to
860    // ssm
861    // if properly registered then
862  0 notifyLoaded = true;
863   
864    }
865    }
866    // FILE LOADED OK
867    // so finally, update the jmol bits and pieces
868    // if (jmolpopup != null)
869    // {
870    // // potential for deadlock here:
871    // // jmolpopup.updateComputedMenus();
872    // }
873  4 if (!isLoadingFromArchive())
874    {
875  4 jmolScript(
876    "model *; select backbone;restrict;cartoon;wireframe off;spacefill off");
877    }
878    // register ourselves as a listener and notify the gui that it needs to
879    // update itself.
880  4 getSsm().addStructureViewerListener(this);
881  4 if (notifyLoaded)
882    {
883  3 FeatureRenderer fr = getFeatureRenderer(null);
884  2 if (fr != null)
885    {
886  2 FeatureSettingsModelI colours = new Pdb().getFeatureColourScheme();
887  2 ((AppJmol) getViewer()).getAlignmentPanel().av
888    .applyFeaturesStyle(colours);
889    }
890  2 refreshGUI();
891  2 loadNotifiesHandled++;
892    }
893  3 setLoadingFromArchive(false);
894    }
895   
 
896  4 toggle protected IProgressIndicator getIProgressIndicator()
897    {
898  4 return null;
899    }
900   
 
901  0 toggle public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
902    {
903  0 notifyAtomPicked(iatom, strMeasure, null);
904    }
905   
906    public abstract void notifyScriptTermination(String strStatus,
907    int msWalltime);
908   
909    /**
910    * display a message echoed from the jmol viewer
911    *
912    * @param strEcho
913    */
914    public abstract void sendConsoleEcho(String strEcho); /*
915    * { showConsole(true);
916    *
917    * history.append("\n" + strEcho); }
918    */
919   
920    // /End JmolStatusListener
921    // /////////////////////////////
922   
923    /**
924    * @param strStatus
925    * status message - usually the response received after a script
926    * executed
927    */
928    public abstract void sendConsoleMessage(String strStatus);
929   
 
930  0 toggle @Override
931    public void setCallbackFunction(String callbackType,
932    String callbackFunction)
933    {
934  0 jalview.bin.Console
935    .errPrintln("Ignoring set-callback request to associate "
936    + callbackType + " with function " + callbackFunction);
937   
938    }
939   
 
940  0 toggle public void showHelp()
941    {
942  0 showUrl("http://wiki.jmol.org"
943    // BH 2018 "http://jmol.sourceforge.net/docs/JmolUserGuide/"
944    , "jmolHelp");
945    }
946   
947    /**
948    * open the URL somehow
949    *
950    * @param target
951    */
952    public abstract void showUrl(String url, String target);
953   
954    /**
955    * called to show or hide the associated console window container.
956    *
957    * @param show
958    */
959    public abstract void showConsole(boolean show);
960   
 
961  49 toggle public static Viewer getJmolData(JmolParser jmolParser)
962    {
963  49 return (Viewer) JmolViewer.allocateViewer(null, null, null, null, null,
964    "-x -o -n", jmolParser);
965    }
966   
967    /**
968    *
969    *
970    *
971    * @param renderPanel
972    * @param jmolfileio
973    * - when true will initialise jmol's file IO system (should be false
974    * in applet context)
975    * @param htmlName
976    * @param documentBase
977    * @param codeBase
978    * @param commandOptions
979    */
 
980  0 toggle public void allocateViewer(Container renderPanel, boolean jmolfileio,
981    String htmlName, URL documentBase, URL codeBase,
982    String commandOptions)
983    {
984  0 allocateViewer(renderPanel, jmolfileio, htmlName, documentBase,
985    codeBase, commandOptions, null, null);
986    }
987   
988    /**
989    *
990    * @param renderPanel
991    * @param jmolfileio
992    * - when true will initialise jmol's file IO system (should be false
993    * in applet context)
994    * @param htmlName
995    * @param documentBase
996    * @param codeBase
997    * @param commandOptions
998    * @param consolePanel
999    * - panel to contain Jmol console
1000    * @param buttonsToShow
1001    * - buttons to show on the console, in order
1002    */
 
1003  5 toggle public void allocateViewer(Container renderPanel, boolean jmolfileio,
1004    String htmlName, URL documentBase, URL codeBase,
1005    String commandOptions, final Container consolePanel,
1006    String buttonsToShow)
1007    {
1008   
1009  5 jalview.bin.Console
1010    .errPrintln("Allocating Jmol Viewer: " + commandOptions);
1011   
1012  5 if (commandOptions == null)
1013    {
1014  0 commandOptions = "";
1015    }
1016  5 jmolViewer = (Viewer) JmolViewer.allocateViewer(renderPanel,
1017  5 (jmolfileio ? new SmarterJmolAdapter() : null),
1018    htmlName + ((Object) this).toString(), documentBase, codeBase,
1019    commandOptions, this);
1020   
1021  5 jmolViewer.setJmolStatusListener(this); // extends JmolCallbackListener
1022   
1023  5 try
1024    {
1025  5 console = createJmolConsole(consolePanel, buttonsToShow);
1026    } catch (Throwable e)
1027    {
1028  0 jalview.bin.Console
1029    .errPrintln("Could not create Jmol application console. "
1030    + e.getMessage());
1031  0 e.printStackTrace();
1032    }
1033  5 if (consolePanel != null)
1034    {
1035  5 consolePanel.addComponentListener(this);
1036   
1037    }
1038   
1039    }
1040   
1041    protected abstract JmolAppConsoleInterface createJmolConsole(
1042    Container consolePanel, String buttonsToShow);
1043   
1044    // BH 2018 -- Jmol console is not working due to problems with styled
1045    // documents.
1046   
1047    protected org.jmol.api.JmolAppConsoleInterface console = null;
1048   
 
1049  0 toggle @Override
1050    public int[] resizeInnerPanel(String data)
1051    {
1052    // Jalview doesn't honour resize panel requests
1053  0 return null;
1054    }
1055   
1056    /**
1057    *
1058    */
 
1059  2 toggle protected void closeConsole()
1060    {
1061  2 if (console != null)
1062    {
1063  2 try
1064    {
1065  2 console.setVisible(false);
1066    } catch (Error e)
1067    {
1068    } catch (Exception x)
1069    {
1070    }
1071  2 ;
1072  2 console = null;
1073    }
1074    }
1075   
1076    /**
1077    * ComponentListener method
1078    */
 
1079  0 toggle @Override
1080    public void componentMoved(ComponentEvent e)
1081    {
1082    }
1083   
1084    /**
1085    * ComponentListener method
1086    */
 
1087  0 toggle @Override
1088    public void componentResized(ComponentEvent e)
1089    {
1090    }
1091   
1092    /**
1093    * ComponentListener method
1094    */
 
1095  0 toggle @Override
1096    public void componentShown(ComponentEvent e)
1097    {
1098  0 showConsole(true);
1099    }
1100   
1101    /**
1102    * ComponentListener method
1103    */
 
1104  0 toggle @Override
1105    public void componentHidden(ComponentEvent e)
1106    {
1107  0 showConsole(false);
1108    }
1109   
1110   
 
1111  15 toggle @Override
1112    protected String getModelIdForFile(String pdbFile)
1113    {
1114  15 if (modelFileNames == null)
1115    {
1116  0 return "";
1117    }
1118  18 for (int i = 0; i < modelFileNames.length; i++)
1119    {
1120  18 if (JmolCommands.filePathMatch(modelFileNames[i],pdbFile))
1121    {
1122  15 return String.valueOf(i + 1);
1123    }
1124    }
1125  0 return "";
1126    }
1127   
 
1128  0 toggle @Override
1129    protected ViewerType getViewerType()
1130    {
1131  0 return ViewerType.JMOL;
1132    }
1133   
 
1134  0 toggle @Override
1135    protected String getModelId(int pdbfnum, String file)
1136    {
1137  0 return String.valueOf(pdbfnum + 1);
1138    }
1139   
1140    /**
1141    * Returns ".spt" - the Jmol session file extension
1142    *
1143    * @return
1144    * @see https://chemapps.stolaf.edu/jmol/docs/#writemodel
1145    */
 
1146  0 toggle @Override
1147    public String getSessionFileExtension()
1148    {
1149  0 return ".spt";
1150    }
1151   
 
1152  0 toggle @Override
1153    public void selectionChanged(BS arg0)
1154    {
1155    // TODO Auto-generated method stub
1156   
1157    }
1158   
 
1159  0 toggle @Override
1160    public SequenceRenderer getSequenceRenderer(AlignmentViewPanel avp)
1161    {
1162  0 return new jalview.gui.SequenceRenderer(avp.getAlignViewport());
1163    }
1164   
 
1165  0 toggle @Override
1166    public String getHelpURL()
1167    {
1168  0 return "http://wiki.jmol.org"; // BH 2018
1169    }
1170    }