Clover icon

Coverage Report

  1. Project Clover database Wed Sep 17 2025 10:52:37 BST
  2. Package jalview.ext.jmol

File JmolParser.java

 

Coverage histogram

../../../img/srcFileCovDistChart7.png
29% of files have more coverage

Code metrics

90
259
38
1
814
609
119
0.46
6.82
38
3.13

Classes

Class Line # Actions
JmolParser 69 259 119
0.661498766.1%
 

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.io.File;
24    import java.io.IOException;
25    import java.util.ArrayList;
26    import java.util.HashMap;
27    import java.util.List;
28    import java.util.Locale;
29    import java.util.Map;
30    import java.util.Vector;
31   
32    import org.jmol.api.JmolStatusListener;
33    import org.jmol.api.JmolViewer;
34    import org.jmol.c.CBK;
35    import org.jmol.c.STR;
36    import org.jmol.modelset.ModelSet;
37    import org.jmol.viewer.Viewer;
38   
39    import com.stevesoft.pat.Regex;
40   
41    import jalview.bin.Console;
42    import jalview.datamodel.Alignment;
43    import jalview.datamodel.AlignmentAnnotation;
44    import jalview.datamodel.Annotation;
45    import jalview.datamodel.PDBEntry;
46    import jalview.datamodel.SequenceI;
47    import jalview.datamodel.annotations.AlphaFoldAnnotationRowBuilder;
48    import jalview.datamodel.annotations.AnnotationRowBuilder;
49    import jalview.datamodel.annotations.QMEANDISCORowBuilder;
50    import jalview.io.DataSourceType;
51    import jalview.io.FileParse;
52    import jalview.io.StructureFile;
53    import jalview.schemes.ResidueProperties;
54    import jalview.structure.StructureImportSettings;
55    import jalview.util.Constants;
56    import jalview.util.Format;
57    import jalview.util.MessageManager;
58    import jalview.ws.dbsources.EBIAlfaFold;
59    import mc_view.Atom;
60    import mc_view.PDBChain;
61    import mc_view.Residue;
62   
63    /**
64    * Import and process files with Jmol for file like PDB, mmCIF
65    *
66    * @author jprocter
67    *
68    */
 
69    public class JmolParser extends StructureFile implements JmolStatusListener
70    {
71    Viewer viewer = null;
72   
 
73  218 toggle public JmolParser(boolean immediate, Object inFile,
74    DataSourceType sourceType) throws IOException
75    {
76    // BH 2018 File or String for filename
77  218 super(immediate, inFile, sourceType);
78   
79    }
80   
 
81  6 toggle public JmolParser(Object inFile, DataSourceType sourceType)
82    throws IOException
83    {
84  6 this(inFile, sourceType, null);
85    }
86   
 
87  21 toggle public JmolParser(Object inFile, DataSourceType sourceType,
88    StructureImportSettings.TFType tempfacType) throws IOException
89    {
90  21 super(inFile, sourceType, tempfacType);
91    }
92   
 
93  5 toggle public JmolParser(FileParse fp, boolean doXferSettings) throws IOException
94    {
95  5 super(fp, doXferSettings);
96    }
97   
 
98  0 toggle public JmolParser(FileParse fp) throws IOException
99    {
100  0 super(fp);
101    }
102   
 
103  1 toggle public JmolParser()
104    {
105    }
106   
107    /**
108    * Calls the Jmol library to parse the PDB/mmCIF file, and then inspects the
109    * resulting object model to generate Jalview-style sequences, with secondary
110    * structure annotation added where available (i.e. where it has been computed
111    * by Jmol using DSSP).
112    *
113    * @see jalview.io.AlignFile#parse()
114    */
 
115  0 toggle @Override
116    public void parse() throws IOException
117    {
118  0 parse(true);
119    }
120   
 
121  244 toggle @Override
122    public void parse(boolean doXferSettings) throws IOException
123    {
124  244 setChains(new Vector<PDBChain>());
125  244 Viewer jmolModel = getJmolData();
126  244 jmolModel.openReader(getDataName(), getDataName(), getReader());
127  244 waitForScript(jmolModel);
128   
129    /*
130    * Convert one or more Jmol Model objects to Jalview sequences
131    */
132  244 if (jmolModel.ms.mc > 0)
133    {
134    // ideally we do this
135    // try
136    // {
137    // setStructureFileType(jmolModel.evalString("show _fileType"));
138    // } catch (Exception q)
139    // {
140    // }
141    // ;
142    // instead, we distinguish .cif from non-.cif by filename
143  244 setStructureFileType(
144  244 getDataName().toLowerCase(Locale.ROOT).endsWith(".cif")
145    ? PDBEntry.Type.MMCIF.toString()
146    : "PDB");
147   
148  244 transformJmolModelToJalview(jmolModel.ms, doXferSettings);
149    }
150    }
151   
152    /**
153    * create a headless jmol instance for dataprocessing
154    *
155    * @return
156    */
 
157  244 toggle private Viewer getJmolData()
158    {
159  244 if (viewer == null)
160    {
161  244 try
162    {
163    /*
164    * params -o (output to sysout) -n (nodisplay) -x (exit when finished)
165    * see http://wiki.jmol.org/index.php/Jmol_Application
166    */
167   
168  244 viewer = JalviewJmolBinding.getJmolData(this);
169    // ensure the 'new' (DSSP) not 'old' (Ramachandran) SS method is used
170  244 viewer.setBooleanProperty("defaultStructureDSSP", true);
171    } catch (ClassCastException x)
172    {
173  0 throw new Error(MessageManager.formatMessage(
174    "error.jmol_version_not_compatible_with_jalview_version",
175    new String[]
176    { JmolViewer.getJmolVersion() }), x);
177    }
178    }
179  244 return viewer;
180    }
181   
 
182  244 toggle public static Regex getNewAlphafoldValidator()
183    {
184  244 Regex validator = new Regex("(AF-[A-Z]+[0-9]+[A-Z0-9]+-F1)");
185  244 validator.setIgnoreCase(true);
186  244 return validator;
187    }
188   
189    PDBEntry.Type jmolFiletype = null;
190   
191    /**
192    * resolve a jmol filetype string and update the jmolFiletype field
193    * accordingly
194    *
195    * @param jmolIdentifiedFileType
196    * @return true if filetype was identified as MMCIF, PDB
197    */
 
198  244 toggle public boolean updateFileType(String jmolIdentifiedFileType)
199    {
200  244 if (jmolIdentifiedFileType == null
201    || jmolIdentifiedFileType.trim().equals(""))
202    {
203  0 return false;
204    }
205  244 if ("mmcif".equalsIgnoreCase(jmolIdentifiedFileType))
206    {
207  56 jmolFiletype = PDBEntry.Type.MMCIF;
208  56 return true;
209    }
210  188 if ("pdb".equalsIgnoreCase(jmolIdentifiedFileType))
211    {
212  188 jmolFiletype = PDBEntry.Type.PDB;
213  188 return true;
214    }
215  0 return false;
216    }
217   
 
218  244 toggle public void transformJmolModelToJalview(ModelSet ms,
219    boolean localDoXferSettings) throws IOException
220    {
221  244 try
222    {
223  244 Regex alphaFold = getNewAlphafoldValidator();
224  244 String lastID = "";
225  244 List<SequenceI> rna = new ArrayList<SequenceI>();
226  244 List<SequenceI> prot = new ArrayList<SequenceI>();
227  244 PDBChain tmpchain;
228  244 String pdbId = (String) ms.getInfo(0, "title");
229  244 boolean isMMCIF = false;
230  244 String jmolFileType_String = (String) ms.getInfo(0, "fileType");
231  244 if (updateFileType(jmolFileType_String))
232    {
233  244 setStructureFileType(jmolFiletype.toString());
234    }
235   
236  244 isMMCIF = PDBEntry.Type.MMCIF.equals(jmolFiletype);
237   
238  244 if (pdbId == null)
239    {
240  91 setId(safeName(getDataName()));
241  91 setPDBIdAvailable(false);
242    }
243    else
244    {
245  153 setId(pdbId);
246  153 setPDBIdAvailable(true);
247  153 setAlphafoldModel(alphaFold.search(pdbId) && isMMCIF);
248    }
249  244 List<Atom> significantAtoms = convertSignificantAtoms(ms);
250  244 for (Atom tmpatom : significantAtoms)
251    {
252  48838 if (tmpatom.resNumIns.trim().equals(lastID))
253    {
254    // phosphorylated protein - seen both CA and P..
255  1 continue;
256    }
257  48837 tmpchain = findChain(tmpatom.chain);
258  48837 if (tmpchain != null)
259    {
260  48501 tmpchain.atoms.addElement(tmpatom);
261    }
262    else
263    {
264  336 AnnotationRowBuilder builder = null;
265  336 if (isAlphafoldModel()
266    || getTemperatureFactorType() == StructureImportSettings.TFType.PLDDT)
267    {
268  79 builder = new AlphaFoldAnnotationRowBuilder();
269    }
270  336 if (getTemperatureFactorType() == StructureImportSettings.TFType.QMEANDISCO)
271    {
272  0 builder = new QMEANDISCORowBuilder();
273    }
274   
275  336 tmpchain = new PDBChain(getId(), tmpatom.chain, builder);
276  336 getChains().add(tmpchain);
277  336 tmpchain.atoms.addElement(tmpatom);
278    }
279  48837 lastID = tmpatom.resNumIns.trim();
280    }
281  244 if (isParseImmediately() && localDoXferSettings)
282    {
283    // configure parsing settings from the static singleton
284  155 xferSettings();
285    }
286   
287  244 makeResidueList();
288  244 makeCaBondList();
289   
290  244 for (PDBChain chain : getChains())
291    {
292  336 SequenceI chainseq = postProcessChain(chain);
293  336 if (isRNA(chainseq))
294    {
295  0 rna.add(chainseq);
296    }
297    else
298    {
299  336 prot.add(chainseq);
300    }
301   
302    // look at local setting for adding secondary tructure
303  336 if (predictSecondaryStructure)
304    {
305  269 createAnnotation(chainseq, chain, ms.at);
306    }
307    }
308    // if Alphafold, fetch the PAE matrix if doesn't already have one
309  244 if (isAlphafoldModel() && !hasPAEMatrix())
310    {
311  32 try
312    {
313  32 Console.info("Retrieving PAE for " + pdbId);
314  32 File paeFile = EBIAlfaFold.fetchAlphaFoldPAE(pdbId, null);
315  32 this.setPAEMatrix(paeFile.getAbsolutePath());
316    } catch (Throwable t)
317    {
318  0 Console.error("Couldn't get the pAE for " + pdbId, t);
319    }
320    }
321    // add a PAEMatrix if set (either by above or otherwise)
322  244 if (hasPAEMatrix())
323    {
324  95 try
325    {
326  95 Alignment al = new Alignment(prot.toArray(new SequenceI[0]));
327  95 EBIAlfaFold.addAlphaFoldPAE(al, new File(this.getPAEMatrix()), 0,
328    null, false, false, null);
329   
330  95 if (al.getAlignmentAnnotation() != null)
331    {
332  95 for (AlignmentAnnotation alann : al.getAlignmentAnnotation())
333    {
334  95 annotations.add(alann);
335    }
336    }
337    } catch (Throwable ff)
338    {
339  0 Console.error("Couldn't import PAE Matrix from " + getPAEMatrix(),
340    ff);
341  0 warningMessage += "Couldn't import PAE Matrix"
342    + getNewlineString() + ff.getLocalizedMessage()
343    + getNewlineString();
344    }
345    }
346    } catch (OutOfMemoryError er)
347    {
348  0 jalview.bin.Console.outPrintln(
349    "OUT OF MEMORY LOADING TRANSFORMING JMOL MODEL TO JALVIEW MODEL");
350  0 throw new IOException(MessageManager
351    .getString("exception.outofmemory_loading_mmcif_file"));
352    }
353    }
354   
 
355  244 toggle private List<Atom> convertSignificantAtoms(ModelSet ms)
356    {
357  244 List<Atom> significantAtoms = new ArrayList<Atom>();
358  244 HashMap<String, org.jmol.modelset.Atom> chainTerMap = new HashMap<String, org.jmol.modelset.Atom>();
359  244 org.jmol.modelset.Atom prevAtom = null;
360  244 for (org.jmol.modelset.Atom atom : ms.at)
361    {
362  269639 if (atom.getAtomName().equalsIgnoreCase("CA")
363    || atom.getAtomName().equalsIgnoreCase("P"))
364    {
365  48866 if (!atomValidated(atom, prevAtom, chainTerMap))
366    {
367  24 continue;
368    }
369  48842 Atom curAtom = new Atom(atom.x, atom.y, atom.z);
370  48842 curAtom.atomIndex = atom.getIndex();
371  48842 curAtom.chain = atom.getChainIDStr();
372  48842 curAtom.insCode = atom.group.getInsertionCode() == '\000' ? ' '
373    : atom.group.getInsertionCode();
374  48842 curAtom.name = atom.getAtomName();
375  48842 curAtom.number = atom.getAtomNumber();
376  48842 curAtom.resName = atom.getGroup3(true);
377  48842 curAtom.resNumber = atom.getResno();
378  48842 curAtom.occupancy = ms.occupancies != null
379    ? ms.occupancies[atom.getIndex()]
380    : Float.valueOf(atom.getOccupancy100());
381  48842 String fmt = new Format("%4i").form(curAtom.resNumber);
382  48842 curAtom.resNumIns = (fmt + curAtom.insCode);
383  48842 curAtom.tfactor = atom.getBfactor100() / 100f;
384  48842 curAtom.type = 0;
385    // significantAtoms.add(curAtom);
386    // ignore atoms from subsequent models
387  48842 if (!significantAtoms.contains(curAtom))
388    {
389  48838 significantAtoms.add(curAtom);
390    }
391  48842 prevAtom = atom;
392    }
393    }
394  244 return significantAtoms;
395    }
396   
 
397  48866 toggle private boolean atomValidated(org.jmol.modelset.Atom curAtom,
398    org.jmol.modelset.Atom prevAtom,
399    HashMap<String, org.jmol.modelset.Atom> chainTerMap)
400    {
401    // jalview.bin.Console.outPrintln("Atom: " + curAtom.getAtomNumber()
402    // + " Last atom index " + curAtom.group.lastAtomIndex);
403  48866 if (chainTerMap == null || prevAtom == null)
404    {
405  244 return true;
406    }
407  48622 String curAtomChId = curAtom.getChainIDStr();
408  48622 String prevAtomChId = prevAtom.getChainIDStr();
409    // new chain encoutered
410  48622 if (!prevAtomChId.equals(curAtomChId))
411    {
412    // On chain switch add previous chain termination to xTerMap if not exists
413  116 if (!chainTerMap.containsKey(prevAtomChId))
414    {
415  104 chainTerMap.put(prevAtomChId, prevAtom);
416    }
417    // if current atom belongs to an already terminated chain and the resNum
418    // diff < 5 then mark as valid and update termination Atom
419  116 if (chainTerMap.containsKey(curAtomChId))
420    {
421  24 if (curAtom.getResno() < chainTerMap.get(curAtomChId).getResno())
422    {
423  0 return false;
424    }
425  24 if ((curAtom.getResno()
426    - chainTerMap.get(curAtomChId).getResno()) < 5)
427    {
428  0 chainTerMap.put(curAtomChId, curAtom);
429  0 return true;
430    }
431  24 return false;
432    }
433    }
434    // atom with previously terminated chain encountered
435  48506 else if (chainTerMap.containsKey(curAtomChId))
436    {
437  0 if (curAtom.getResno() < chainTerMap.get(curAtomChId).getResno())
438    {
439  0 return false;
440    }
441  0 if ((curAtom.getResno()
442    - chainTerMap.get(curAtomChId).getResno()) < 5)
443    {
444  0 chainTerMap.put(curAtomChId, curAtom);
445  0 return true;
446    }
447  0 return false;
448    }
449    // HETATM with resNum jump > 2
450  48598 return !(curAtom.isHetero()
451    && ((curAtom.getResno() - prevAtom.getResno()) > 2));
452    }
453   
 
454  269 toggle private void createAnnotation(SequenceI sequence, PDBChain chain,
455    org.jmol.modelset.Atom[] jmolAtoms)
456    {
457  269 char[] secstr = new char[sequence.getLength()];
458  269 char[] secstrcode = new char[sequence.getLength()];
459   
460    // Ensure Residue size equals Seq size
461  269 if (chain.residues.size() != sequence.getLength())
462    {
463  0 return;
464    }
465  269 int annotIndex = 0;
466  269 for (Residue residue : chain.residues)
467    {
468  41382 Atom repAtom = residue.getAtoms().get(0);
469  41382 STR proteinStructureSubType = jmolAtoms[repAtom.atomIndex].group
470    .getProteinStructureSubType();
471  41382 setSecondaryStructure(proteinStructureSubType, annotIndex, secstr,
472    secstrcode);
473  41382 ++annotIndex;
474    }
475  269 addSecondaryStructureAnnotation(chain.pdbid, sequence, secstr,
476    secstrcode, chain.id, sequence.getStart());
477    }
478   
479    /**
480    * Helper method that adds an AlignmentAnnotation for secondary structure to
481    * the sequence, provided at least one secondary structure assignment has been
482    * made
483    *
484    * @param modelTitle
485    * @param seq
486    * @param secstr
487    * @param secstrcode
488    * @param chainId
489    * @param firstResNum
490    * @return
491    */
 
492  269 toggle protected void addSecondaryStructureAnnotation(String modelTitle,
493    SequenceI sq, char[] secstr, char[] secstrcode, String chainId,
494    int firstResNum)
495    {
496  269 int length = sq.getLength();
497  269 boolean ssFound = false;
498  269 Annotation asecstr[] = new Annotation[length
499    + (firstResNum - sq.getStart())];
500  41651 for (int p = 0; p < length; p++)
501    {
502  41382 if (secstr[p] >= 'A' && secstr[p] <= 'z')
503    {
504  16229 try
505    {
506  16229 asecstr[p] = new Annotation(null, null, secstrcode[p], Float.NaN);
507  16229 ssFound = true;
508    } catch (Exception e)
509    {
510    // e.printStackTrace();
511    }
512    }
513    }
514   
515  269 if (ssFound)
516    {
517  247 String mt = modelTitle == null ? getDataName() : modelTitle;
518  247 mt += chainId;
519  247 AlignmentAnnotation ann = new AlignmentAnnotation(
520    "Secondary Structure", "Secondary Structure for " + mt,
521    asecstr);
522  247 ann.belowAlignment = true;
523  247 ann.visible = true;
524  247 ann.autoCalculated = false;
525  247 ann.setCalcId(getClass().getName());
526  247 ann.adjustForAlignment();
527  247 ann.validateRangeAndDisplay();
528   
529  247 if (modelTitle != null)
530    {
531  247 ann.setProperty(Constants.PDBID, modelTitle);
532    }
533   
534  247 if (chainId != null)
535    {
536  247 ann.setProperty(Constants.CHAINID, chainId);
537    }
538  247 annotations.add(ann);
539  247 sq.addAlignmentAnnotation(ann);
540    }
541    }
542   
 
543  244 toggle private void waitForScript(Viewer jmd)
544    {
545  244 while (jmd.isScriptExecuting())
546    {
547  0 try
548    {
549  0 Thread.sleep(50);
550   
551    } catch (InterruptedException x)
552    {
553    }
554    }
555    }
556   
557    /**
558    * Convert Jmol's secondary structure code to Jalview's, and stored it in the
559    * secondary structure arrays at the given sequence position
560    *
561    * @param proteinStructureSubType
562    * @param pos
563    * @param secstr
564    * @param secstrcode
565    */
 
566  41388 toggle protected void setSecondaryStructure(STR proteinStructureSubType, int pos,
567    char[] secstr, char[] secstrcode)
568    {
569  41388 switch (proteinStructureSubType)
570    {
571  752 case HELIX310:
572  752 secstr[pos] = '3';
573  752 break;
574  4177 case HELIX:
575  5405 case HELIXALPHA:
576  9582 secstr[pos] = 'H';
577  9582 break;
578  1 case HELIXPI:
579  1 secstr[pos] = 'P';
580  1 break;
581  6650 case SHEET:
582  6650 secstr[pos] = 'E';
583  6650 break;
584  24403 default:
585  24403 secstr[pos] = 0;
586    }
587   
588  41388 switch (proteinStructureSubType)
589    {
590  752 case HELIX310:
591  5405 case HELIXALPHA:
592  1 case HELIXPI:
593  4177 case HELIX:
594  10335 secstrcode[pos] = 'H';
595  10335 break;
596  6650 case SHEET:
597  6650 secstrcode[pos] = 'E';
598  6650 break;
599  24403 default:
600  24403 secstrcode[pos] = 0;
601    }
602    }
603   
604    /**
605    * Convert any non-standard peptide codes to their standard code table
606    * equivalent. (Initial version only does Selenomethionine MSE->MET.)
607    *
608    * @param threeLetterCode
609    * @param seq
610    * @param pos
611    */
 
612  0 toggle protected void replaceNonCanonicalResidue(String threeLetterCode,
613    char[] seq, int pos)
614    {
615  0 String canonical = ResidueProperties
616    .getCanonicalAminoAcid(threeLetterCode);
617  0 if (canonical != null && !canonical.equalsIgnoreCase(threeLetterCode))
618    {
619  0 seq[pos] = ResidueProperties.getSingleCharacterCode(canonical);
620    }
621    }
622   
623    /**
624    * Not implemented - returns null
625    */
 
626  0 toggle @Override
627    public String print(SequenceI[] seqs, boolean jvSuffix)
628    {
629  0 return null;
630    }
631   
632    /**
633    * Not implemented
634    */
 
635  0 toggle @Override
636    public void setCallbackFunction(String callbackType,
637    String callbackFunction)
638    {
639    }
640   
 
641  0 toggle @Override
642    public void notifyCallback(CBK cbType, Object[] data)
643    {
644  0 String strInfo = (data == null || data[1] == null ? null
645    : data[1].toString());
646  0 switch (cbType)
647    {
648  0 case ECHO:
649  0 sendConsoleEcho(strInfo);
650  0 break;
651  0 case SCRIPT:
652  0 notifyScriptTermination((String) data[2],
653    ((Integer) data[3]).intValue());
654  0 break;
655  0 case MEASURE:
656  0 String mystatus = (String) data[3];
657  0 if (mystatus.indexOf("Picked") >= 0
658    || mystatus.indexOf("Sequence") >= 0)
659    {
660    // Picking mode
661  0 sendConsoleMessage(strInfo);
662    }
663  0 else if (mystatus.indexOf("Completed") >= 0)
664    {
665  0 sendConsoleEcho(strInfo.substring(strInfo.lastIndexOf(",") + 2,
666    strInfo.length() - 1));
667    }
668  0 break;
669  0 case MESSAGE:
670  0 sendConsoleMessage(data == null ? null : strInfo);
671  0 break;
672  0 case PICK:
673  0 sendConsoleMessage(strInfo);
674  0 break;
675  0 default:
676  0 break;
677    }
678    }
679   
680    String lastConsoleEcho = "";
681   
 
682  0 toggle private void sendConsoleEcho(String string)
683    {
684  0 lastConsoleEcho += string;
685  0 lastConsoleEcho += "\n";
686    }
687   
688    String lastConsoleMessage = "";
689   
 
690  0 toggle private void sendConsoleMessage(String string)
691    {
692  0 lastConsoleMessage += string;
693  0 lastConsoleMessage += "\n";
694    }
695   
696    int lastScriptTermination = -1;
697   
698    String lastScriptMessage = "";
699   
 
700  0 toggle private void notifyScriptTermination(String string, int intValue)
701    {
702  0 lastScriptMessage += string;
703  0 lastScriptMessage += "\n";
704  0 lastScriptTermination = intValue;
705    }
706   
 
707  0 toggle @Override
708    public boolean notifyEnabled(CBK callbackPick)
709    {
710  0 switch (callbackPick)
711    {
712  0 case MESSAGE:
713  0 case SCRIPT:
714  0 case ECHO:
715  0 case LOADSTRUCT:
716  0 case ERROR:
717  0 return true;
718  0 default:
719  0 return false;
720    }
721    }
722   
723    /**
724    * Not implemented - returns null
725    */
 
726  0 toggle @Override
727    public String eval(String strEval)
728    {
729  0 return null;
730    }
731   
732    /**
733    * Not implemented - returns null
734    */
 
735  0 toggle @Override
736    public float[][] functionXY(String functionName, int x, int y)
737    {
738  0 return null;
739    }
740   
741    /**
742    * Not implemented - returns null
743    */
 
744  0 toggle @Override
745    public float[][][] functionXYZ(String functionName, int nx, int ny,
746    int nz)
747    {
748  0 return null;
749    }
750   
751    /**
752    * Not implemented - returns null
753    */
 
754  0 toggle @Override
755    public String createImage(String fileName, String imageType,
756    Object text_or_bytes, int quality)
757    {
758  0 return null;
759    }
760   
761    /**
762    * Not implemented - returns null
763    */
 
764  0 toggle @Override
765    public Map<String, Object> getRegistryInfo()
766    {
767  0 return null;
768    }
769   
770    /**
771    * Not implemented
772    */
 
773  0 toggle @Override
774    public void showUrl(String url)
775    {
776    }
777   
778    /**
779    * Not implemented - returns null
780    */
 
781  0 toggle @Override
782    public int[] resizeInnerPanel(String data)
783    {
784  0 return null;
785    }
786   
 
787  0 toggle @Override
788    public Map<String, Object> getJSpecViewProperty(String arg0)
789    {
790  0 return null;
791    }
792   
 
793  0 toggle public boolean isPredictSecondaryStructure()
794    {
795  0 return predictSecondaryStructure;
796    }
797   
 
798  0 toggle public void setPredictSecondaryStructure(
799    boolean predictSecondaryStructure)
800    {
801  0 this.predictSecondaryStructure = predictSecondaryStructure;
802    }
803   
 
804  0 toggle public boolean isVisibleChainAnnotation()
805    {
806  0 return visibleChainAnnotation;
807    }
808   
 
809  0 toggle public void setVisibleChainAnnotation(boolean visibleChainAnnotation)
810    {
811  0 this.visibleChainAnnotation = visibleChainAnnotation;
812    }
813   
814    }