Clover icon

Coverage Report

  1. Project Clover database Fri Nov 15 2024 13:56:46 GMT
  2. Package jalview.ext.jmol

File JalviewJmolBinding.java

 

Coverage histogram

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

Code metrics

136
309
49
1
1,154
786
150
0.49
6.31
49
3.06

Classes

Class Line # Actions
JalviewJmolBinding 66 309 150
0.536437353.6%
 

Contributing tests

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