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.PDBEntry;
26 import jalview.datamodel.SequenceI;
27 import jalview.io.FileParse;
28 import jalview.io.StructureFile;
29 import jalview.schemes.ResidueProperties;
30 import jalview.structure.StructureImportSettings;
31 import jalview.util.Format;
32 import jalview.util.MessageManager;
34 import java.io.IOException;
35 import java.util.ArrayList;
36 import java.util.HashMap;
37 import java.util.List;
39 import java.util.Vector;
41 import javajs.awt.Dimension;
43 import org.jmol.api.JmolStatusListener;
44 import org.jmol.api.JmolViewer;
45 import org.jmol.c.CBK;
46 import org.jmol.c.STR;
47 import org.jmol.modelset.ModelSet;
48 import org.jmol.viewer.Viewer;
51 import MCview.PDBChain;
52 import MCview.Residue;
55 * Import and process files with Jmol for file like PDB, mmCIF
60 public class JmolParser extends StructureFile implements JmolStatusListener
64 public JmolParser(String inFile, String type) throws IOException
69 public JmolParser(FileParse fp) throws IOException
79 * Calls the Jmol library to parse the PDB/mmCIF file, and then inspects the
80 * resulting object model to generate Jalview-style sequences, with secondary
81 * structure annotation added where available (i.e. where it has been computed
82 * by Jmol using DSSP).
84 * @see jalview.io.AlignFile#parse()
87 public void parse() throws IOException
89 setChains(new Vector<PDBChain>());
90 Viewer jmolModel = getJmolData();
91 jmolModel.openReader(getDataName(), getDataName(), getReader());
92 waitForScript(jmolModel);
95 * Convert one or more Jmol Model objects to Jalview sequences
97 if (jmolModel.ms.mc > 0)
102 // setStructureFileType(jmolModel.evalString("show _fileType"));
103 // } catch (Exception q)
107 // instead, we distinguish .cif from non-.cif by filename
108 setStructureFileType(getDataName().toLowerCase().endsWith(".cif") ? PDBEntry.Type.MMCIF
109 .toString() : "PDB");
111 transformJmolModelToJalview(jmolModel.ms);
116 * create a headless jmol instance for dataprocessing
120 private Viewer getJmolData()
127 * params -o (output to sysout) -n (nodisplay) -x (exit when finished)
128 * see http://wiki.jmol.org/index.php/Jmol_Application
130 viewer = (Viewer) JmolViewer.allocateViewer(null, null, null, null,
131 null, "-x -o -n", this);
132 // ensure the 'new' (DSSP) not 'old' (Ramachandran) SS method is used
133 viewer.setBooleanProperty("defaultStructureDSSP", true);
134 } catch (ClassCastException x)
136 throw new Error(MessageManager.formatMessage(
137 "error.jmol_version_not_compatible_with_jalview_version",
138 new String[] { JmolViewer.getJmolVersion() }), x);
144 public void transformJmolModelToJalview(ModelSet ms) throws IOException
149 List<SequenceI> rna = new ArrayList<SequenceI>();
150 List<SequenceI> prot = new ArrayList<SequenceI>();
152 String pdbId = (String) ms.getInfo(0, "title");
156 setId(safeName(getDataName()));
157 setPDBIdAvailable(false);
162 setPDBIdAvailable(true);
164 List<Atom> significantAtoms = convertSignificantAtoms(ms);
165 for (Atom tmpatom : significantAtoms)
169 tmpchain = findChain(tmpatom.chain);
170 if (tmpatom.resNumIns.trim().equals(lastID))
172 // phosphorylated protein - seen both CA and P..
175 tmpchain.atoms.addElement(tmpatom);
176 } catch (Exception e)
178 tmpchain = new PDBChain(getId(), tmpatom.chain);
179 getChains().add(tmpchain);
180 tmpchain.atoms.addElement(tmpatom);
182 lastID = tmpatom.resNumIns.trim();
193 // always use resource name, not the hardwired file
194 // Does the value of ID get used ? Behaviour needs to be
195 // documented and tested
196 setId(getDataName());
198 >>>>>>> spike/JAL-2040_JAL-2137_phyre2
199 for (PDBChain chain : getChains())
201 SequenceI chainseq = postProcessChain(chain);
211 if (StructureImportSettings.isProcessSecondaryStructure())
213 createAnnotation(chainseq, chain, ms.at);
216 } catch (OutOfMemoryError er)
219 .println("OUT OF MEMORY LOADING TRANSFORMING JMOL MODEL TO JALVIEW MODEL");
220 throw new IOException(
222 .getString("exception.outofmemory_loading_mmcif_file"));
226 private List<Atom> convertSignificantAtoms(ModelSet ms)
228 List<Atom> significantAtoms = new ArrayList<Atom>();
229 HashMap<String, org.jmol.modelset.Atom> chainTerMap = new HashMap<String, org.jmol.modelset.Atom>();
230 org.jmol.modelset.Atom prevAtom = null;
231 for (org.jmol.modelset.Atom atom : ms.at)
233 if (atom.getAtomName().equalsIgnoreCase("CA")
234 || atom.getAtomName().equalsIgnoreCase("P"))
236 if (!atomValidated(atom, prevAtom, chainTerMap))
240 Atom curAtom = new Atom(atom.x, atom.y, atom.z);
241 curAtom.atomIndex = atom.getIndex();
242 curAtom.chain = atom.getChainIDStr();
243 curAtom.insCode = atom.group.getInsertionCode() == '\000' ? ' '
244 : atom.group.getInsertionCode();
245 curAtom.name = atom.getAtomName();
246 curAtom.number = atom.getAtomNumber();
247 curAtom.resName = atom.getGroup3(true);
248 curAtom.resNumber = atom.getResno();
249 curAtom.occupancy = ms.occupancies != null ? ms.occupancies[atom
250 .getIndex()] : Float.valueOf(atom.getOccupancy100());
251 String fmt = new Format("%4i").form(curAtom.resNumber);
252 curAtom.resNumIns = (fmt + curAtom.insCode);
253 curAtom.tfactor = atom.getBfactor100() / 100f;
255 // significantAtoms.add(curAtom);
256 // ignore atoms from subsequent models
257 if (!significantAtoms.contains(curAtom))
259 significantAtoms.add(curAtom);
264 return significantAtoms;
267 private boolean atomValidated(org.jmol.modelset.Atom curAtom,
268 org.jmol.modelset.Atom prevAtom,
269 HashMap<String, org.jmol.modelset.Atom> chainTerMap)
271 // System.out.println("Atom: " + curAtom.getAtomNumber()
272 // + " Last atom index " + curAtom.group.lastAtomIndex);
273 if (chainTerMap == null || prevAtom == null)
277 String curAtomChId = curAtom.getChainIDStr();
278 String prevAtomChId = prevAtom.getChainIDStr();
279 // new chain encoutered
280 if (!prevAtomChId.equals(curAtomChId))
282 // On chain switch add previous chain termination to xTerMap if not exists
283 if (!chainTerMap.containsKey(prevAtomChId))
285 chainTerMap.put(prevAtomChId, prevAtom);
287 // if current atom belongs to an already terminated chain and the resNum
288 // diff < 5 then mark as valid and update termination Atom
289 if (chainTerMap.containsKey(curAtomChId))
291 if (curAtom.getResno() < chainTerMap.get(curAtomChId).getResno())
295 if ((curAtom.getResno() - chainTerMap.get(curAtomChId).getResno()) < 5)
297 chainTerMap.put(curAtomChId, curAtom);
303 // atom with previously terminated chain encountered
304 else if (chainTerMap.containsKey(curAtomChId))
306 if (curAtom.getResno() < chainTerMap.get(curAtomChId).getResno())
310 if ((curAtom.getResno() - chainTerMap.get(curAtomChId).getResno()) < 5)
312 chainTerMap.put(curAtomChId, curAtom);
317 // HETATM with resNum jump > 2
318 return !(curAtom.isHetero() && ((curAtom.getResno() - prevAtom
322 private void createAnnotation(SequenceI sequence, PDBChain chain,
323 org.jmol.modelset.Atom[] jmolAtoms)
325 char[] secstr = new char[sequence.getLength()];
326 char[] secstrcode = new char[sequence.getLength()];
328 // Ensure Residue size equals Seq size
329 if (chain.residues.size() != sequence.getLength())
334 for (Residue residue : chain.residues)
336 Atom repAtom = residue.getAtoms().get(0);
337 STR proteinStructureSubType = jmolAtoms[repAtom.atomIndex].group
338 .getProteinStructureSubType();
339 setSecondaryStructure(proteinStructureSubType, annotIndex, secstr,
343 addSecondaryStructureAnnotation(chain.pdbid, sequence, secstr,
344 secstrcode, chain.id, sequence.getStart());
348 * Helper method that adds an AlignmentAnnotation for secondary structure to
349 * the sequence, provided at least one secondary structure prediction has been
360 protected void addSecondaryStructureAnnotation(String modelTitle,
361 SequenceI sq, char[] secstr, char[] secstrcode, String chainId,
364 char[] seq = sq.getSequence();
365 boolean ssFound = false;
366 Annotation asecstr[] = new Annotation[seq.length + firstResNum - 1];
367 for (int p = 0; p < seq.length; p++)
369 if (secstr[p] >= 'A' && secstr[p] <= 'z')
373 asecstr[p] = new Annotation(String.valueOf(secstr[p]), null,
374 secstrcode[p], Float.NaN);
376 } catch (Exception e)
378 // e.printStackTrace();
385 String mt = modelTitle == null ? getDataName() : modelTitle;
387 AlignmentAnnotation ann = new AlignmentAnnotation(
388 "Secondary Structure", "Secondary Structure for " + mt,
390 ann.belowAlignment = true;
392 ann.autoCalculated = false;
393 ann.setCalcId(getClass().getName());
394 ann.adjustForAlignment();
395 ann.validateRangeAndDisplay();
396 annotations.add(ann);
397 sq.addAlignmentAnnotation(ann);
401 private void waitForScript(Viewer jmd)
403 while (jmd.isScriptExecuting())
409 } catch (InterruptedException x)
416 * Convert Jmol's secondary structure code to Jalview's, and stored it in the
417 * secondary structure arrays at the given sequence position
419 * @param proteinStructureSubType
424 protected void setSecondaryStructure(STR proteinStructureSubType,
425 int pos, char[] secstr, char[] secstrcode)
427 switch (proteinStructureSubType)
446 switch (proteinStructureSubType)
452 secstrcode[pos] = 'H';
455 secstrcode[pos] = 'E';
463 * Convert any non-standard peptide codes to their standard code table
464 * equivalent. (Initial version only does Selenomethionine MSE->MET.)
466 * @param threeLetterCode
470 protected void replaceNonCanonicalResidue(String threeLetterCode,
473 String canonical = ResidueProperties
474 .getCanonicalAminoAcid(threeLetterCode);
475 if (canonical != null && !canonical.equalsIgnoreCase(threeLetterCode))
477 seq[pos] = ResidueProperties.getSingleCharacterCode(canonical);
482 * Not implemented - returns null
485 public String print()
494 public void setCallbackFunction(String callbackType,
495 String callbackFunction)
500 public void notifyCallback(CBK cbType, Object[] data)
502 String strInfo = (data == null || data[1] == null ? null : data[1]
507 sendConsoleEcho(strInfo);
510 notifyScriptTermination((String) data[2],
511 ((Integer) data[3]).intValue());
514 String mystatus = (String) data[3];
515 if (mystatus.indexOf("Picked") >= 0
516 || mystatus.indexOf("Sequence") >= 0)
519 sendConsoleMessage(strInfo);
521 else if (mystatus.indexOf("Completed") >= 0)
523 sendConsoleEcho(strInfo.substring(strInfo.lastIndexOf(",") + 2,
524 strInfo.length() - 1));
528 sendConsoleMessage(data == null ? null : strInfo);
531 sendConsoleMessage(strInfo);
538 String lastConsoleEcho = "";
540 private void sendConsoleEcho(String string)
542 lastConsoleEcho += string;
543 lastConsoleEcho += "\n";
546 String lastConsoleMessage = "";
548 private void sendConsoleMessage(String string)
550 lastConsoleMessage += string;
551 lastConsoleMessage += "\n";
554 int lastScriptTermination = -1;
556 String lastScriptMessage = "";
558 private void notifyScriptTermination(String string, int intValue)
560 lastScriptMessage += string;
561 lastScriptMessage += "\n";
562 lastScriptTermination = intValue;
566 public boolean notifyEnabled(CBK callbackPick)
568 switch (callbackPick)
582 * Not implemented - returns null
585 public String eval(String strEval)
591 * Not implemented - returns null
594 public float[][] functionXY(String functionName, int x, int y)
600 * Not implemented - returns null
603 public float[][][] functionXYZ(String functionName, int nx, int ny, int nz)
609 * Not implemented - returns null
612 public String createImage(String fileName, String imageType,
613 Object text_or_bytes, int quality)
619 * Not implemented - returns null
622 public Map<String, Object> getRegistryInfo()
631 public void showUrl(String url)
636 * Not implemented - returns null
639 public Dimension resizeInnerPanel(String data)
645 public Map<String, Object> getJSpecViewProperty(String arg0)
650 public boolean isPredictSecondaryStructure()
652 return predictSecondaryStructure;
655 public void setPredictSecondaryStructure(boolean predictSecondaryStructure)
657 this.predictSecondaryStructure = predictSecondaryStructure;
660 public boolean isVisibleChainAnnotation()
662 return visibleChainAnnotation;
665 public void setVisibleChainAnnotation(boolean visibleChainAnnotation)
667 this.visibleChainAnnotation = visibleChainAnnotation;