/*
* Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
* Copyright (C) 2014 The Jalview Authors
*
* This file is part of Jalview.
*
* Jalview is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* Jalview is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jalview. If not, see .
* The Jalview Authors are detailed in the 'AUTHORS' file.
*/
package jalview.ext.jmol;
import jalview.datamodel.AlignmentAnnotation;
import jalview.datamodel.Annotation;
import jalview.datamodel.PDBEntry;
import jalview.datamodel.Sequence;
import jalview.datamodel.SequenceI;
import jalview.io.AlignFile;
import jalview.io.FileParse;
import jalview.schemes.ResidueProperties;
import jalview.util.MessageManager;
import java.io.IOException;
import java.util.Hashtable;
import java.util.Map;
import org.jmol.api.JmolStatusListener;
import org.jmol.api.JmolViewer;
import org.jmol.constant.EnumCallback;
import org.jmol.modelset.Group;
import org.jmol.modelset.Model;
import org.jmol.modelset.ModelSet;
import org.jmol.modelset.Polymer;
import org.jmol.modelsetbio.BioPolymer;
import org.jmol.viewer.Viewer;
import org.openscience.jmol.app.JmolApp;
/**
* Import and process PDB files with Jmol
*
* @author jprocter
*
*/
public class PDBFileWithJmol extends AlignFile implements
JmolStatusListener
{
JmolApp jmolApp = null;
Viewer viewer = null;
public PDBFileWithJmol(String inFile, String type) throws IOException
{
super(inFile, type);
}
public PDBFileWithJmol(FileParse fp) throws IOException
{
super(fp);
}
public PDBFileWithJmol()
{
// TODO Auto-generated constructor stub
}
/**
* create a headless jmol instance for dataprocessing
*
* @return
*/
private Viewer getJmolData()
{
if (viewer == null)
{ // note that -o -n -x are all implied
jmolApp = new JmolApp();
jmolApp.isDataOnly = true;
jmolApp.haveConsole = false;
jmolApp.haveDisplay = false;
jmolApp.exitUponCompletion = true;
try
{
viewer = (Viewer) JmolViewer.allocateViewer(null, null, null, null,
null, jmolApp.commandOptions, this);
viewer.setScreenDimension(jmolApp.startupWidth,
jmolApp.startupHeight);
jmolApp.startViewer(viewer, null);
} catch (ClassCastException x)
{
throw new Error(MessageManager.formatMessage("error.jmol_version_not_compatible_with_jalview_version", new String[]{JmolViewer.getJmolVersion()}),
x);
}
}
return viewer;
}
private void waitForScript(Viewer jmd)
{
while (jmd.isScriptExecuting())
{
try
{
Thread.sleep(50);
} catch (InterruptedException x)
{
}
}
}
/*
* (non-Javadoc)
*
* @see jalview.io.AlignFile#parse()
*/
@Override
public void parse() throws IOException
{
Viewer jmd = getJmolData();
jmd.openReader(getDataName(), getDataName(), getReader());
waitForScript(jmd);
if (jmd.getModelCount() > 0)
{
ModelSet ms = jmd.getModelSet();
String structs = ms.calculateStructures(null, true, false, true);
// System.out.println("Structs\n"+structs);
for (Model model : ms.getModels())
{
for (int _bp = 0, _bpc = model.getBioPolymerCount(); _bp < _bpc; _bp++)
{
Polymer bp = model.getBioPolymer(_bp);
if (bp instanceof BioPolymer)
{
BioPolymer biopoly = (BioPolymer) bp;
char _lastChainId = 0;
int[] groups = biopoly.getLeadAtomIndices();
Group[] bpgrp = biopoly.getGroups();
char seq[] = new char[groups.length], secstr[] = new char[groups.length], secstrcode[] = new char[groups.length];
int groupc = 0, len = 0, firstrnum = 1, lastrnum = 0;
do
{
if (groupc >= groups.length
|| ms.atoms[groups[groupc]].getChainID() != _lastChainId)
{
if (len > 0)
{
boolean isNa = (biopoly.isDna() || biopoly.isRna());
// normalise sequence from Jmol to jalview
int[] cinds = isNa ? ResidueProperties.nucleotideIndex : ResidueProperties.aaIndex;
int nonGap = isNa ? ResidueProperties.maxNucleotideIndex
: ResidueProperties.maxProteinIndex;
char ngc = 'X';
char newseq[] = new char[len];
Annotation asecstr[] = new Annotation[len+firstrnum-1];
for (int p = 0; p < len; p++)
{
newseq[p] = cinds[seq[p]] == nonGap ? ngc : seq[p];
if (secstr[p] >= 'A' && secstr[p] <= 'z')
{
asecstr[p] = new Annotation("" + secstr[p], null,
secstrcode[p], Float.NaN);
}
}
SequenceI sq = new Sequence("" + getDataName() + "|"
+ model.getModelTitle() + "|" + _lastChainId,
newseq, firstrnum, lastrnum);
PDBEntry pdbe = new PDBEntry();
pdbe.setFile(getDataName());
pdbe.setId(getDataName());
sq.addPDBId(pdbe);
pdbe.setProperty(new Hashtable());
pdbe.getProperty().put("CHAIN", "" + _lastChainId);
// JAL-1533
// Need to put the number of models for this polymer somewhere for Chimera/others to grab
// pdbe.getProperty().put("PDBMODELS", biopoly.)
seqs.add(sq);
if (!isNa)
{
String mt = model.getModelTitle() == null ? getDataName()
: model.getModelTitle();
if (_lastChainId >= ' ')
{
mt += _lastChainId;
}
AlignmentAnnotation ann = new AlignmentAnnotation(
"Secondary Structure",
"Secondary Structure for " + mt, asecstr);
ann.belowAlignment=true;
ann.visible=true;
ann.autoCalculated=false;
ann.setCalcId(getClass().getName());
sq.addAlignmentAnnotation(ann);
ann.adjustForAlignment();
ann.validateRangeAndDisplay();
annotations.add(ann);
}
}
len = 0;
firstrnum = 1;
lastrnum = 0;
}
if (groupc < groups.length)
{
if (len == 0)
{
firstrnum = bpgrp[groupc].getResno();
_lastChainId = bpgrp[groupc].getChainID();
}
else
{
lastrnum = bpgrp[groupc].getResno();
}
seq[len] = bpgrp[groupc].getGroup1();
switch (bpgrp[groupc].getProteinStructureSubType())
{
case HELIX_310:
if (secstr[len] == 0)
{
secstr[len] = '3';
}
case HELIX_ALPHA:
if (secstr[len] == 0)
{
secstr[len] = 'H';
}
case HELIX_PI:
if (secstr[len] == 0)
{
secstr[len] = 'P';
}
case HELIX:
if (secstr[len] == 0)
{
secstr[len] = 'H';
}
secstrcode[len] = 'H';
break;
case SHEET:
secstr[len] = 'E';
secstrcode[len] = 'E';
break;
default:
secstr[len] = 0;
secstrcode[len] = 0;
}
len++;
}
} while (groupc++ < groups.length);
}
}
}
/*
* lastScriptTermination = -9465; String dsspOut =
* jmd.evalString("calculate STRUCTURE"); if (dsspOut.equals("pending")) {
* while (lastScriptTermination == -9465) { try { Thread.sleep(50); }
* catch (Exception x) { } ; } } System.out.println(lastConsoleEcho);
*/
}
}
/*
* (non-Javadoc)
*
* @see jalview.io.AlignFile#print()
*/
@Override
public String print()
{
// TODO Auto-generated method stub
return null;
}
@Override
public void setCallbackFunction(String callbackType,
String callbackFunction)
{
// TODO Auto-generated method stub
}
/*
* @Override public void notifyCallback(EnumCallback type, Object[] data) {
* try { switch (type) { case ERROR: case SCRIPT:
* notifyScriptTermination((String) data[2], ((Integer) data[3]).intValue());
* break; case MESSAGE: sendConsoleMessage((data == null) ? ((String) null) :
* (String) data[1]); break; case LOADSTRUCT: notifyFileLoaded((String)
* data[1], (String) data[2], (String) data[3], (String) data[4], ((Integer)
* data[5]).intValue());
*
* break; default: // System.err.println("Unhandled callback " + type + " " //
* + data[1].toString()); break; } } catch (Exception e) {
* System.err.println("Squashed Jmol callback handler error:");
* e.printStackTrace(); } }
*/
public void notifyCallback(EnumCallback type, Object[] data)
{
String strInfo = (data == null || data[1] == null ? null : data[1]
.toString());
switch (type)
{
case ECHO:
sendConsoleEcho(strInfo);
break;
case SCRIPT:
notifyScriptTermination((String) data[2],
((Integer) data[3]).intValue());
break;
case MEASURE:
String mystatus = (String) data[3];
if (mystatus.indexOf("Picked") >= 0
|| mystatus.indexOf("Sequence") >= 0)
{
// Picking mode
sendConsoleMessage(strInfo);
}
else if (mystatus.indexOf("Completed") >= 0)
{
sendConsoleEcho(strInfo.substring(strInfo.lastIndexOf(",") + 2,
strInfo.length() - 1));
}
break;
case MESSAGE:
sendConsoleMessage(data == null ? null : strInfo);
break;
case PICK:
sendConsoleMessage(strInfo);
break;
default:
break;
}
}
private void notifyFileLoaded(String string, String string2,
String string3, String string4, int intValue)
{
// TODO Auto-generated method stub
}
String lastConsoleEcho = "";
private void sendConsoleEcho(String string)
{
lastConsoleEcho += string;
lastConsoleEcho += "\n";
}
String lastConsoleMessage = "";
private void sendConsoleMessage(String string)
{
lastConsoleMessage += string;
lastConsoleMessage += "\n";
}
int lastScriptTermination = -1;
String lastScriptMessage = "";
private void notifyScriptTermination(String string, int intValue)
{
lastScriptMessage += string;
lastScriptMessage += "\n";
lastScriptTermination = intValue;
}
@Override
public boolean notifyEnabled(EnumCallback callbackPick)
{
switch (callbackPick)
{
case MESSAGE:
case SCRIPT:
case ECHO:
case LOADSTRUCT:
case ERROR:
return true;
case MEASURE:
case PICK:
case HOVER:
case RESIZE:
case SYNC:
case CLICK:
case ANIMFRAME:
case MINIMIZATION:
}
return false;
}
@Override
public String eval(String strEval)
{
// TODO Auto-generated method stub
return null;
}
@Override
public float[][] functionXY(String functionName, int x, int y)
{
// TODO Auto-generated method stub
return null;
}
@Override
public float[][][] functionXYZ(String functionName, int nx, int ny, int nz)
{
// TODO Auto-generated method stub
return null;
}
@Override
public String createImage(String fileName, String type,
Object text_or_bytes, int quality)
{
// TODO Auto-generated method stub
return null;
}
@Override
public Map getRegistryInfo()
{
// TODO Auto-generated method stub
return null;
}
@Override
public void showUrl(String url)
{
// TODO Auto-generated method stub
}
@Override
public void resizeInnerPanel(String data)
{
// TODO Auto-generated method stub
}
}