2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
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.
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.
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.
21 package jalview.ext.jmol;
23 import jalview.datamodel.AlignmentAnnotation;
24 import jalview.datamodel.Annotation;
25 import jalview.datamodel.DBRefSource;
26 import jalview.datamodel.SequenceI;
27 import jalview.io.FileParse;
28 import jalview.io.StructureFile;
29 import jalview.schemes.ResidueProperties;
30 import jalview.structure.StructureViewSettings;
31 import jalview.util.MessageManager;
33 import java.io.IOException;
34 import java.util.ArrayList;
35 import java.util.List;
37 import java.util.Vector;
39 import javajs.awt.Dimension;
41 import org.jmol.api.JmolStatusListener;
42 import org.jmol.api.JmolViewer;
43 import org.jmol.c.CBK;
44 import org.jmol.c.STR;
45 import org.jmol.modelset.ModelSet;
46 import org.jmol.viewer.Viewer;
49 import MCview.PDBChain;
50 import MCview.Residue;
53 * Import and process files with Jmol for file like PDB, mmCIF
58 public class JmolParser extends StructureFile implements JmolStatusListener
62 public JmolParser(boolean addAlignmentAnnotations, boolean predictSecStr,
63 boolean externalSecStr, String inFile, String type)
69 public JmolParser(boolean addAlignmentAnnotations, boolean predictSecStr,
70 boolean externalSecStr, FileParse fp) throws IOException
80 * Calls the Jmol library to parse the PDB/mmCIF file, and then inspects the
81 * resulting object model to generate Jalview-style sequences, with secondary
82 * structure annotation added where available (i.e. where it has been computed
83 * by Jmol using DSSP).
85 * @see jalview.io.AlignFile#parse()
88 public void parse() throws IOException
90 String dataName = getDataName();
91 if (dataName.endsWith(".cif"))
93 setDbRefType(DBRefSource.MMCIF);
97 setDbRefType(DBRefSource.PDB);
99 setChains(new Vector<PDBChain>());
100 Viewer jmolModel = getJmolData();
101 jmolModel.openReader(getDataName(), getDataName(), getReader());
102 waitForScript(jmolModel);
105 * Convert one or more Jmol Model objects to Jalview sequences
107 if (jmolModel.ms.mc > 0)
109 transformJmolModelToJalview(jmolModel.ms);
114 * create a headless jmol instance for dataprocessing
118 private Viewer getJmolData()
124 viewer = (Viewer) JmolViewer.allocateViewer(null, null, null, null,
125 null, "-x -o -n", this);
126 // ensure the 'new' (DSSP) not 'old' (Ramachandran) SS method is used
127 viewer.setBooleanProperty("defaultStructureDSSP", true);
128 } catch (ClassCastException x)
130 throw new Error(MessageManager.formatMessage(
131 "error.jmol_version_not_compatible_with_jalview_version",
132 new String[] { JmolViewer.getJmolVersion() }), x);
138 public void transformJmolModelToJalview(ModelSet ms) throws IOException
143 List<SequenceI> rna = new ArrayList<SequenceI>();
144 List<SequenceI> prot = new ArrayList<SequenceI>();
146 String pdbId = (String) ms.getInfo(0, "title");
148 List<Atom> significantAtoms = convertSignificantAtoms(ms);
149 for (Atom tmpatom : significantAtoms)
153 tmpchain = findChain(tmpatom.chain);
154 if (tmpatom.resNumIns.trim().equals(lastID))
156 // phosphorylated protein - seen both CA and P..
159 tmpchain.atoms.addElement(tmpatom);
160 } catch (Exception e)
162 tmpchain = new PDBChain(pdbId, tmpatom.chain);
163 getChains().add(tmpchain);
164 tmpchain.atoms.addElement(tmpatom);
166 lastID = tmpatom.resNumIns.trim();
175 // always use resource name, not the hardwired file
176 // Does the value of ID get used ? Behaviour needs to be
177 // documented and tested
178 setId(getDataName());
180 for (PDBChain chain : getChains())
182 SequenceI chainseq = postProcessChain(chain);
192 if (StructureViewSettings.isPredictSecondaryStructure())
194 createAnnotation(chainseq, chain, ms.at);
197 } catch (OutOfMemoryError er)
200 .println("OUT OF MEMORY LOADING TRANSFORMING JMOL MODEL TO JALVIEW MODEL");
201 throw new IOException(
203 .getString("exception.outofmemory_loading_mmcif_file"));
207 private List<Atom> convertSignificantAtoms(ModelSet ms)
209 List<Atom> significantAtoms = new ArrayList<Atom>();
210 for (org.jmol.modelset.Atom atom : ms.at)
212 // System.out.println("Seq Id : " + atom.getSeqID());
213 // System.out.println("To String : " + atom.toString());
218 if (atom.getAtomName().equalsIgnoreCase("CA")
219 || atom.getAtomName().equalsIgnoreCase("P"))
221 Atom curAtom = new Atom(atom.x, atom.y, atom.z);
222 curAtom.atomIndex = atom.getIndex();
223 curAtom.chain = atom.getChainIDStr();
224 curAtom.insCode = atom.group.getInsertionCode();
225 curAtom.name = atom.getAtomName();
226 curAtom.number = atom.getAtomNumber();
227 curAtom.resName = atom.getGroup3(true);
228 curAtom.resNumber = atom.getResno();
229 curAtom.occupancy = ms.occupancies != null ? ms.occupancies[atom
230 .getIndex()] : Float.valueOf(atom.getOccupancy100());
231 curAtom.resNumIns = "" + curAtom.resNumber + curAtom.insCode;
232 curAtom.tfactor = atom.getBfactor100() / 100f;
234 significantAtoms.add(curAtom);
237 return significantAtoms;
240 private void createAnnotation(SequenceI sequence, PDBChain chain,
241 org.jmol.modelset.Atom[] jmolAtoms)
243 char[] secstr = new char[sequence.getLength()];
244 char[] secstrcode = new char[sequence.getLength()];
246 // Ensure Residue size equals Seq size
247 if (chain.residues.size() != sequence.getLength())
252 for (Residue residue : chain.residues)
254 Atom repAtom = residue.getAtoms().get(0);
255 STR proteinStructureSubType = jmolAtoms[repAtom.atomIndex].group
256 .getProteinStructureSubType();
257 setSecondaryStructure(proteinStructureSubType, annotIndex, secstr,
261 addSecondaryStructureAnnotation(chain.pdbid, sequence, secstr,
262 secstrcode, chain.id, sequence.getStart());
266 * Helper method that adds an AlignmentAnnotation for secondary structure to
267 * the sequence, provided at least one secondary structure prediction has been
278 protected void addSecondaryStructureAnnotation(String modelTitle,
279 SequenceI sq, char[] secstr, char[] secstrcode, String chainId,
282 char[] seq = sq.getSequence();
283 boolean ssFound = false;
284 Annotation asecstr[] = new Annotation[seq.length + firstResNum - 1];
285 for (int p = 0; p < seq.length; p++)
287 if (secstr[p] >= 'A' && secstr[p] <= 'z')
291 asecstr[p] = new Annotation(String.valueOf(secstr[p]), null,
292 secstrcode[p], Float.NaN);
294 } catch (Exception e)
296 // e.printStackTrace();
303 String mt = modelTitle == null ? getDataName() : modelTitle;
305 AlignmentAnnotation ann = new AlignmentAnnotation(
306 "Secondary Structure", "Secondary Structure for " + mt,
308 ann.belowAlignment = true;
310 ann.autoCalculated = false;
311 ann.setCalcId(getClass().getName());
312 ann.adjustForAlignment();
313 ann.validateRangeAndDisplay();
314 annotations.add(ann);
315 sq.addAlignmentAnnotation(ann);
319 private void waitForScript(Viewer jmd)
321 while (jmd.isScriptExecuting())
327 } catch (InterruptedException x)
334 * Convert Jmol's secondary structure code to Jalview's, and stored it in the
335 * secondary structure arrays at the given sequence position
337 * @param proteinStructureSubType
342 protected void setSecondaryStructure(STR proteinStructureSubType,
343 int pos, char[] secstr, char[] secstrcode)
345 switch (proteinStructureSubType)
364 switch (proteinStructureSubType)
370 secstrcode[pos] = 'H';
373 secstrcode[pos] = 'E';
381 * Convert any non-standard peptide codes to their standard code table
382 * equivalent. (Initial version only does Selenomethionine MSE->MET.)
384 * @param threeLetterCode
388 protected void replaceNonCanonicalResidue(String threeLetterCode,
391 String canonical = ResidueProperties
392 .getCanonicalAminoAcid(threeLetterCode);
393 if (canonical != null && !canonical.equalsIgnoreCase(threeLetterCode))
395 seq[pos] = ResidueProperties.getSingleCharacterCode(canonical);
400 * Not implemented - returns null
403 public String print()
412 public void setCallbackFunction(String callbackType,
413 String callbackFunction)
418 public void notifyCallback(CBK cbType, Object[] data)
420 String strInfo = (data == null || data[1] == null ? null : data[1]
425 sendConsoleEcho(strInfo);
428 notifyScriptTermination((String) data[2],
429 ((Integer) data[3]).intValue());
432 String mystatus = (String) data[3];
433 if (mystatus.indexOf("Picked") >= 0
434 || mystatus.indexOf("Sequence") >= 0)
437 sendConsoleMessage(strInfo);
439 else if (mystatus.indexOf("Completed") >= 0)
441 sendConsoleEcho(strInfo.substring(strInfo.lastIndexOf(",") + 2,
442 strInfo.length() - 1));
446 sendConsoleMessage(data == null ? null : strInfo);
449 sendConsoleMessage(strInfo);
456 String lastConsoleEcho = "";
458 private void sendConsoleEcho(String string)
460 lastConsoleEcho += string;
461 lastConsoleEcho += "\n";
464 String lastConsoleMessage = "";
466 private void sendConsoleMessage(String string)
468 lastConsoleMessage += string;
469 lastConsoleMessage += "\n";
472 int lastScriptTermination = -1;
474 String lastScriptMessage = "";
476 private void notifyScriptTermination(String string, int intValue)
478 lastScriptMessage += string;
479 lastScriptMessage += "\n";
480 lastScriptTermination = intValue;
484 public boolean notifyEnabled(CBK callbackPick)
486 switch (callbackPick)
500 * Not implemented - returns null
503 public String eval(String strEval)
509 * Not implemented - returns null
512 public float[][] functionXY(String functionName, int x, int y)
518 * Not implemented - returns null
521 public float[][][] functionXYZ(String functionName, int nx, int ny, int nz)
527 * Not implemented - returns null
530 public String createImage(String fileName, String imageType,
531 Object text_or_bytes, int quality)
537 * Not implemented - returns null
540 public Map<String, Object> getRegistryInfo()
549 public void showUrl(String url)
554 * Not implemented - returns null
557 public Dimension resizeInnerPanel(String data)
563 public Map<String, Object> getJSpecViewProperty(String arg0)
568 public boolean isPredictSecondaryStructure()
570 return predictSecondaryStructure;
573 public void setPredictSecondaryStructure(boolean predictSecondaryStructure)
575 this.predictSecondaryStructure = predictSecondaryStructure;
578 public boolean isVisibleChainAnnotation()
580 return visibleChainAnnotation;
583 public void setVisibleChainAnnotation(boolean visibleChainAnnotation)
585 this.visibleChainAnnotation = visibleChainAnnotation;