X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Fjalview%2Fext%2Frbvi%2Fchimera%2FJalviewChimeraBinding.java;h=b5bfbaaf350a639f794d2bb4a10a37e56e383b5d;hb=b5d61763044c1d72f06ce0e50da2171422a3774b;hp=a39f355c85e1c6ec5b4b4a4ce962808a2e6594ee;hpb=aced09c4feeaf3406269442c14e54abeeb4cad81;p=jalview.git diff --git a/src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java b/src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java index a39f355..b5bfbaa 100644 --- a/src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java +++ b/src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java @@ -44,10 +44,9 @@ import java.io.File; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; -import java.util.Hashtable; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.Vector; import ext.edu.ucsf.rbvi.strucviz2.ChimeraManager; import ext.edu.ucsf.rbvi.strucviz2.ChimeraModel; @@ -59,6 +58,13 @@ public abstract class JalviewChimeraBinding extends SequenceStructureBinding, StructureSelectionManagerProvider { + + private static final boolean debug = false; + + private static final String PHOSPHORUS = "P"; + + private static final String ALPHACARBON = "CA"; + private StructureManager csm; private ChimeraManager viewer; @@ -71,13 +77,14 @@ public abstract class JalviewChimeraBinding extends private boolean loadingFromArchive = false; /** - * second flag to indicate if the jmol viewer should ignore sequence colouring - * events from the structure manager because the GUI is still setting up + * second flag to indicate if the Chimera viewer should ignore sequence + * colouring events from the structure manager because the GUI is still + * setting up */ private boolean loadingFinished = true; /** - * state flag used to check if the Jmol viewer's paint method can be called + * state flag used to check if the Chimera viewer's paint method can be called */ private boolean finishedInit = false; @@ -95,18 +102,18 @@ public abstract class JalviewChimeraBinding extends /** * when true, try to search the associated datamodel for sequences that are - * associated with any unknown structures in the Jmol view. + * associated with any unknown structures in the Chimera view. */ private boolean associateNewStructs = false; - Vector atomsPicked = new Vector(); + List atomsPicked = new ArrayList(); - public Vector chainNames; + public List chainNames; - Hashtable chainFile; + private Map chainFile; /** - * array of target chains for seuqences - tied to pdbentry and sequence[] + * array of target chains for sequences - tied to pdbentry and sequence[] */ protected String[][] chains; @@ -116,7 +123,7 @@ public abstract class JalviewChimeraBinding extends public String fileLoadingError; - private Map> chimmaps = new HashMap>(); + private Map> chimmaps = new LinkedHashMap>(); private List mdlToFile = new ArrayList(); @@ -138,7 +145,7 @@ public abstract class JalviewChimeraBinding extends try { List oldList = viewer.getModelList(); - viewer.openModel(file, ModelType.PDB_MODEL); + viewer.openModel(file, pe.getId(), ModelType.PDB_MODEL); List newList = viewer.getModelList(); if (oldList.size() < newList.size()) { @@ -170,7 +177,7 @@ public abstract class JalviewChimeraBinding extends } catch (Error e) { } - // Explicitly map to the filename used by Jmol ; + // Explicitly map to the filename used by Chimera ; // pdbentry[pe].getFile(), protocol); if (ssm != null) @@ -233,13 +240,6 @@ public abstract class JalviewChimeraBinding extends } viewer = new ChimeraManager( csm = new ext.edu.ucsf.rbvi.strucviz2.StructureManager(true)); - /* - * viewer = JmolViewer.allocateViewer(renderPanel, new SmarterJmolAdapter(), - * "jalviewJmol", ap.av.applet .getDocumentBase(), - * ap.av.applet.getCodeBase(), "", this); - * - * jmolpopup = JmolPopup.newJmolPopup(viewer, true, "Jmol", true); - */ } public JalviewChimeraBinding(StructureSelectionManager ssm, @@ -251,12 +251,13 @@ public abstract class JalviewChimeraBinding extends } /** - * construct a title string for the viewer window based on the data jalview + * Construct a title string for the viewer window based on the data Jalview * knows about * + * @param verbose * @return */ - public String getViewerTitle() + public String getViewerTitle(boolean verbose) { if (sequence == null || pdbentry == null || sequence.length < 1 || pdbentry.length < 1 || sequence[0].length < 1) @@ -265,20 +266,24 @@ public abstract class JalviewChimeraBinding extends } // TODO: give a more informative title when multiple structures are // displayed. - StringBuffer title = new StringBuffer("Chimera view for " - + sequence[0][0].getName() + ":" + pdbentry[0].getId()); + StringBuilder title = new StringBuilder(64); + title.append("Chimera view for " + sequence[0][0].getName() + ":" + + pdbentry[0].getId()); - if (pdbentry[0].getProperty() != null) + if (verbose) { - if (pdbentry[0].getProperty().get("method") != null) + if (pdbentry[0].getProperty() != null) { - title.append(" Method: "); - title.append(pdbentry[0].getProperty().get("method")); - } - if (pdbentry[0].getProperty().get("chains") != null) - { - title.append(" Chain:"); - title.append(pdbentry[0].getProperty().get("chains")); + if (pdbentry[0].getProperty().get("method") != null) + { + title.append(" Method: "); + title.append(pdbentry[0].getProperty().get("method")); + } + if (pdbentry[0].getProperty().get("chains") != null) + { + title.append(" Chain:"); + title.append(pdbentry[0].getProperty().get("chains")); + } } } return title.toString(); @@ -288,47 +293,52 @@ public abstract class JalviewChimeraBinding extends * prepare the view for a given set of models/chains. chainList contains * strings of the form 'pdbfilename:Chaincode' * - * @param chainList + * @param toshow * list of chains to make visible */ - public void centerViewer(Vector chainList) + public void centerViewer(List toshow) { - StringBuffer cmd = new StringBuffer(); - String lbl; + StringBuilder cmd = new StringBuilder(64); int mlength, p; - for (int i = 0, iSize = chainList.size(); i < iSize; i++) + for (String lbl : toshow) { mlength = 0; - lbl = (String) chainList.elementAt(i); do { p = mlength; mlength = lbl.indexOf(":", p); } while (p < mlength && mlength < (lbl.length() - 2)); // TODO: lookup each pdb id and recover proper model number for it. - cmd.append("#" + getModelNum((String) chainFile.get(lbl)) + "." + cmd.append("#" + getModelNum(chainFile.get(lbl)) + "." + lbl.substring(mlength + 1) + " or "); } if (cmd.length() > 0) + { cmd.setLength(cmd.length() - 4); - evalStateCommand("~display #*; ~ribbon #*; ribbon " + cmd + ";focus " - + cmd,false); + } + String cmdstring = cmd.toString(); + evalStateCommand("~display #*; ~ribbon #*; ribbon " + cmdstring + + ";focus " + cmdstring, false); } - public void closeViewer() + /** + * Close down the Jalview viewer, and (optionally) the associate Chimera + * window. + */ + public void closeViewer(boolean closeChimera) { ssm.removeStructureViewerListener(this, this.getPdbFile()); - // and shut down Chimera - viewer.exitChimera(); - // viewer.evalStringQuiet("zap"); - // viewer.setJmolStatusListener(null); + if (closeChimera) + { + viewer.exitChimera(); + } lastCommand = null; viewer = null; releaseUIResources(); } /** - * called by JalviewJmolbinding after closeViewer is called - release any + * called by JalviewChimerabinding after closeViewer is called - release any * resources and references so they can be garbage collected. */ protected abstract void releaseUIResources(); @@ -336,17 +346,15 @@ public abstract class JalviewChimeraBinding extends public void colourByChain() { colourBySequence = false; - // TODO: colour by chain should colour each chain distinctly across all - // visible models - // TODO: http://issues.jalview.org/browse/JAL-628 - evalStateCommand("select *;color chain",false); + evalStateCommand("rainbow chain", false); } public void colourByCharge() { colourBySequence = false; - evalStateCommand("colour *;color white;select ASP,GLU;color red;" - + "select LYS,ARG;color blue;select CYS;color yellow", false); + evalStateCommand( + "color white;color red ::ASP;color red ::GLU;color blue ::LYS;color blue ::ARG;color yellow ::CYS", + false); } /** @@ -394,9 +402,9 @@ public abstract class JalviewChimeraBinding extends int[] _refStructure, ColumnSelection[] _hiddenCols) { assert (_alignment.length == _refStructure.length && _alignment.length != _hiddenCols.length); - StringBuffer allComs = new StringBuffer(); // whole shebang for superposition + StringBuilder allComs = new StringBuilder(128); // Chimera superposition cmd String[] files = getPdbFile(); - // check to see if we are still waiting for Jmol files + // check to see if we are still waiting for Chimera files long starttime = System.currentTimeMillis(); boolean waiting = true; do @@ -427,7 +435,7 @@ public abstract class JalviewChimeraBinding extends if (waiting) { System.err - .println("RUNTIME PROBLEM: Jmol seems to be taking a long time to process all the structures."); + .println("RUNTIME PROBLEM: Chimera seems to be taking a long time to process all the structures."); return; } refreshPdbEntries(); @@ -455,7 +463,6 @@ public abstract class JalviewChimeraBinding extends { refStructure = -1; } - StringBuffer command = new StringBuffer(); boolean matched[] = new boolean[alignment.getWidth()]; for (int m = 0; m < matched.length; m++) @@ -466,10 +473,9 @@ public abstract class JalviewChimeraBinding extends int commonrpositions[][] = new int[files.length][alignment.getWidth()]; String isel[] = new String[files.length]; - // reference structure - all others are superposed in it String[] targetC = new String[files.length]; String[] chainNames = new String[files.length]; - String[] atomS = new String[files.length]; + String[] atomSpec = new String[files.length]; for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++) { StructureMapping[] mapping = ssm.getMapping(files[pdbfnum]); @@ -536,7 +542,7 @@ public abstract class JalviewChimeraBinding extends } chainNames[pdbfnum] = mapping[m].getPdbId() + targetC[pdbfnum]; - atomS[pdbfnum] = asp.getRNA()!=null ? "P" : "CA"; + atomSpec[pdbfnum] = asp.getRNA() != null ? PHOSPHORUS : ALPHACARBON; // move on to next pdb file s = sequence[pdbfnum].length; break; @@ -619,6 +625,7 @@ public abstract class JalviewChimeraBinding extends } } } + StringBuilder command = new StringBuilder(256); for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++) { if (pdbfnum == refStructure || selcom[pdbfnum] == null @@ -626,26 +633,36 @@ public abstract class JalviewChimeraBinding extends { continue; } - if (command.length()>0) + if (command.length() > 0) { command.append(";"); } - command.append("match"); - // form the matched pair strings - for (int s = 0; s < 2; s++) - { - command.append(" #"+(s == 0 ? pdbfnum : refStructure)+".1"); - // note - need to select on first model, otherwise it all goes wrong! - command.append(selcom[(s == 0 ? pdbfnum : refStructure)]); - command.append("@"+atomS[(s == 0 ? pdbfnum : refStructure)]); // match on backbone alpha/polyphosphate - } + /* + * Form Chimera match command, from the 'new' structure to the + * 'reference' structure e.g. (residues 1-91, chain B/A, alphacarbons): + * + * match #1:1-91.B@CA #0:1-91.A@CA + * + * @see + * https://www.cgl.ucsf.edu/chimera/docs/UsersGuide/midas/match.html + */ + command.append("match #" + pdbfnum /* +".1" */); + // TODO: handle sub-models + command.append(selcom[pdbfnum]); + command.append("@" + atomSpec[pdbfnum]); + command.append(" #" + refStructure /* +".1" */); + command.append(selcom[refStructure]); + command.append("@" + atomSpec[refStructure]); } if (selectioncom.length() > 0) { - System.out.println("Select regions:\n" + selectioncom.toString()); - System.out - .println("Superimpose command(s):\n" + command.toString()); + if (debug) + { + System.out.println("Select regions:\n" + selectioncom.toString()); + System.out.println("Superimpose command(s):\n" + + command.toString()); + } allComs.append("~display all; chain @CA|P; ribbon " + selectioncom.toString() + ";"+command.toString()); // selcom.append("; ribbons; "); @@ -657,11 +674,14 @@ public abstract class JalviewChimeraBinding extends { selectioncom.setLength(selectioncom.length() - 1); } - System.out.println("Select regions:\n" + selectioncom.toString()); + if (debug) + { + System.out.println("Select regions:\n" + selectioncom.toString()); + } allComs.append("; ~display all; chain @CA|P; ribbon " - + selectioncom.toString() + ""); + + selectioncom.toString() + "; focus"); // evalStateCommand("select *; backbone; select "+selcom.toString()+"; cartoons; center "+selcom.toString()); - evalStateCommand(allComs.toString(),false); + evalStateCommand(allComs.toString(), true /* false */); } } @@ -678,7 +698,24 @@ public abstract class JalviewChimeraBinding extends } } - public void evalStateCommand(final String command, boolean resp) + /** + * Answers true if the Chimera process is still running, false if ended or not + * started. + * + * @return + */ + public boolean isChimeraRunning() + { + return viewer.isChimeraLaunched(); + } + + /** + * Send a command to Chimera, and optionally log any responses. + * + * @param command + * @param logResponse + */ + public void evalStateCommand(final String command, boolean logResponse) { viewerCommandHistory(false); checkLaunched(); @@ -689,8 +726,9 @@ public abstract class JalviewChimeraBinding extends // @Override // public void run() // { - lastReply = viewer.sendChimeraCommand(command, resp); - if (debug) + // trim command or it may never find a match in the replyLog!! + lastReply = viewer.sendChimeraCommand(command.trim(), logResponse); + if (debug && logResponse) { log("Response from command ('" + command + "') was:\n" + lastReply); @@ -719,7 +757,9 @@ public abstract class JalviewChimeraBinding extends jalview.api.AlignmentViewPanel alignmentv) { if (!colourBySequence || !loadingFinished) + { return; + } if (ssm == null) { return; @@ -738,17 +778,19 @@ public abstract class JalviewChimeraBinding extends for (jalview.structure.StructureMappingcommandSet cpdbbyseq : ChimeraCommands .getColourBySequenceCommand(ssm, files, sequence, sr, fr, alignment)) + { for (String cbyseq : cpdbbyseq.commands) { waitForChimera(); evalStateCommand(cbyseq, false); waitForChimera(); } + } } private void waitForChimera() { - while (viewer.isBusy()) + while (viewer != null && viewer.isBusy()) { try { Thread.sleep(15); @@ -767,25 +809,6 @@ public abstract class JalviewChimeraBinding extends this.colourBySequence = colourBySequence; } - public void createImage(String file, String type, int quality) - { - System.out.println("JMOL CREATE IMAGE"); - } - - public String createImage(String fileName, String type, - Object textOrBytes, int quality) - { - System.out.println("JMOL CREATE IMAGE"); - return null; - } - - public String eval(String strEval) - { - // System.out.println(strEval); - // "# 'eval' is implemented only for the applet."; - return null; - } - // End StructureListener // ////////////////////////// @@ -804,7 +827,9 @@ public abstract class JalviewChimeraBinding extends String pdbfile) { if (getModelNum(pdbfile) < 0) + { return null; + } log("get model / residue colour attribute unimplemented"); return null; } @@ -837,7 +862,9 @@ public abstract class JalviewChimeraBinding extends for (int i = 0; i < mfn.length; i++) { if (mfn[i].equalsIgnoreCase(modelFileName)) + { return i; + } } return -1; } @@ -935,8 +962,6 @@ public abstract class JalviewChimeraBinding extends } } - boolean debug = true; - private void log(String message) { System.err.println("## Chimera log: " + message); @@ -944,8 +969,8 @@ public abstract class JalviewChimeraBinding extends private void viewerCommandHistory(boolean enable) { - log("(Not yet implemented) History " - + ((debug || enable) ? "on" : "off")); + // log("(Not yet implemented) History " + // + ((debug || enable) ? "on" : "off")); } public void loadInline(String string) @@ -996,8 +1021,10 @@ public abstract class JalviewChimeraBinding extends String chainId; if (strInfo.indexOf(":") > -1) + { chainId = strInfo.substring(strInfo.indexOf(":") + 1, strInfo.indexOf(".")); + } else { chainId = " "; @@ -1035,7 +1062,9 @@ public abstract class JalviewChimeraBinding extends ; } if (lastMessage == null || !lastMessage.equals(strInfo)) + { ssm.mouseOverStructure(pdbResNum, chainId, pdbfilename); + } lastMessage = strInfo; } @@ -1054,13 +1083,17 @@ public abstract class JalviewChimeraBinding extends int chainSeparator = strInfo.indexOf(":"); int p = 0; if (chainSeparator == -1) + { chainSeparator = strInfo.indexOf("."); + } String picked = strInfo.substring(strInfo.indexOf("]") + 1, chainSeparator); String mdlString = ""; if ((p = strInfo.indexOf(":")) > -1) + { picked += strInfo.substring(p + 1, strInfo.indexOf(".")); + } if ((p = strInfo.indexOf("/")) > -1) { @@ -1073,12 +1106,12 @@ public abstract class JalviewChimeraBinding extends if (!atomsPicked.contains(picked)) { viewer.select(picked); - atomsPicked.addElement(picked); + atomsPicked.add(picked); } else { viewer.select("not " + picked); - atomsPicked.removeElement(picked); + atomsPicked.remove(picked); } viewerCommandHistory(true); // TODO: in application this happens @@ -1093,7 +1126,7 @@ public abstract class JalviewChimeraBinding extends // incremented every time a load notification is successfully handled - // lightweight mechanism for other threads to detect when they can start - // referrring to new structures. + // referring to new structures. private long loadNotifiesHandled = 0; public long getLoadNotifiesHandled() @@ -1119,8 +1152,8 @@ public abstract class JalviewChimeraBinding extends fileLoadingError = null; String[] oldmodels = modelFileNames; modelFileNames = null; - chainNames = new Vector(); - chainFile = new Hashtable(); + chainNames = new ArrayList(); + chainFile = new HashMap(); boolean notifyLoaded = false; String[] modelfilenames = getPdbFile(); // first check if we've lost any structures @@ -1181,49 +1214,43 @@ public abstract class JalviewChimeraBinding extends colourBySequence = false; if (cs == null) + { return; + } String res; int index; Color col; + // Chimera expects RBG values in the range 0-1 + final double normalise = 255D; viewerCommandHistory(false); // TODO: Switch between nucleotide or aa selection expressions Enumeration en = ResidueProperties.aa3Hash.keys(); - StringBuffer command = new StringBuffer("select *;color white;"); + StringBuilder command = new StringBuilder(128); + command.append("color white;"); while (en.hasMoreElements()) { res = en.nextElement().toString(); index = ((Integer) ResidueProperties.aa3Hash.get(res)).intValue(); if (index > 20) + { continue; + } col = cs.findColour(ResidueProperties.aa[index].charAt(0)); - // TODO: need colour string function and res selection here - command.append("select " + res + ";color[" + col.getRed() + "," - + col.getGreen() + "," + col.getBlue() + "];"); + command.append("color " + col.getRed() / normalise + "," + + col.getGreen() / normalise + "," + col.getBlue() + / normalise + " ::" + res + ";"); } evalStateCommand(command.toString(),false); viewerCommandHistory(true); } - public void showHelp() - { - // chimera help - showUrl("http://jmol.sourceforge.net/docs/JmolUserGuide/", "jmolHelp"); - } - /** - * open the URL somehow - * - * @param target - */ - public abstract void showUrl(String url, String target); - - /** - * called when the binding thinks the UI needs to be refreshed after a Jmol + * called when the binding thinks the UI needs to be refreshed after a Chimera * state change. this could be because structures were loaded, or because an - * error has occured. + * error has occurred. */ public abstract void refreshGUI(); @@ -1252,8 +1279,8 @@ public abstract class JalviewChimeraBinding extends /** * - * @return true if Jmol is still restoring state or loading is still going on - * (see setFinsihedLoadingFromArchive) + * @return true if Chimeral is still restoring state or loading is still going + * on (see setFinsihedLoadingFromArchive) */ public boolean isLoadingFromArchive() { @@ -1271,13 +1298,22 @@ public abstract class JalviewChimeraBinding extends loadingFinished = finishedLoading; } - public void setBackgroundColour(java.awt.Color col) + /** + * Send the Chimera 'background solid " command. + * + * @see https + * ://www.cgl.ucsf.edu/chimera/current/docs/UsersGuide/midas/background + * .html + * @param col + */ + public void setBackgroundColour(Color col) { viewerCommandHistory(false); - // todo set background colour - viewer.sendChimeraCommand( - "background [" + col.getRed() + "," + col.getGreen() + "," - + col.getBlue() + "];", false); + double normalise = 255D; + final String command = "background solid " + col.getRed() / normalise + "," + + col.getGreen() / normalise + "," + col.getBlue() + / normalise + ";"; + viewer.sendChimeraCommand(command, false); viewerCommandHistory(true); } @@ -1289,21 +1325,20 @@ public abstract class JalviewChimeraBinding extends public synchronized PDBEntry[] addSequenceAndChain(PDBEntry[] pdbe, SequenceI[][] seq, String[][] chns) { - int pe = -1; - Vector v = new Vector(); - Vector rtn = new Vector(); + List v = new ArrayList(); + List rtn = new ArrayList(); for (int i = 0; i < pdbentry.length; i++) { - v.addElement(pdbentry[i]); + v.add(pdbentry[i]); } for (int i = 0; i < pdbe.length; i++) { int r = v.indexOf(pdbe[i]); if (r == -1 || r >= pdbentry.length) { - rtn.addElement(new int[] + rtn.add(new int[] { v.size(), i }); - v.addElement(pdbe[i]); + v.add(pdbe[i]); } else { @@ -1311,12 +1346,11 @@ public abstract class JalviewChimeraBinding extends addSequenceAndChain(r, seq[i], chns[i]); } } - pdbe = new PDBEntry[v.size()]; - v.copyInto(pdbe); + pdbe = v.toArray(new PDBEntry[v.size()]); pdbentry = pdbe; if (rtn.size() > 0) { - // expand the tied seuqence[] and string[] arrays + // expand the tied sequence[] and string[] arrays SequenceI[][] sqs = new SequenceI[pdbentry.length][]; String[][] sch = new String[pdbentry.length][]; System.arraycopy(sequence, 0, sqs, 0, sequence.length); @@ -1326,7 +1360,7 @@ public abstract class JalviewChimeraBinding extends pdbe = new PDBEntry[rtn.size()]; for (int r = 0; r < pdbe.length; r++) { - int[] stri = ((int[]) rtn.elementAt(r)); + int[] stri = (rtn.get(r)); // record the pdb file as a new addition pdbe[r] = pdbentry[stri[0]]; // and add the new sequence/chain entries @@ -1340,9 +1374,14 @@ public abstract class JalviewChimeraBinding extends return pdbe; } + /** + * Adds sequences to the pe'th pdbentry's sequence set. + * + * @param pe + * @param seq + */ public void addSequence(int pe, SequenceI[] seq) { - // add sequences to the pe'th pdbentry's seuqence set. addSequenceAndChain(pe, seq, null); } @@ -1350,11 +1389,14 @@ public abstract class JalviewChimeraBinding extends { if (pe < 0 || pe >= pdbentry.length) { - throw new Error(MessageManager.formatMessage("error.implementation_error_no_pdbentry_from_index", new String[]{Integer.valueOf(pe).toString()})); + throw new Error(MessageManager.formatMessage( + "error.implementation_error_no_pdbentry_from_index", + new Object[] + { Integer.valueOf(pe).toString() })); } final String nullChain = "TheNullChain"; - Vector s = new Vector(); - Vector c = new Vector(); + List s = new ArrayList(); + List c = new ArrayList(); if (chains == null) { chains = new String[pdbentry.length][]; @@ -1363,23 +1405,23 @@ public abstract class JalviewChimeraBinding extends { for (int i = 0; i < sequence[pe].length; i++) { - s.addElement(sequence[pe][i]); + s.add(sequence[pe][i]); if (chains[pe] != null) { if (i < chains[pe].length) { - c.addElement(chains[pe][i]); + c.add(chains[pe][i]); } else { - c.addElement(nullChain); + c.add(nullChain); } } else { if (tchain != null && tchain.length > 0) { - c.addElement(nullChain); + c.add(nullChain); } } } @@ -1388,20 +1430,18 @@ public abstract class JalviewChimeraBinding extends { if (!s.contains(seq[i])) { - s.addElement(seq[i]); + s.add(seq[i]); if (tchain != null && i < tchain.length) { - c.addElement(tchain[i] == null ? nullChain : tchain[i]); + c.add(tchain[i] == null ? nullChain : tchain[i]); } } } - SequenceI[] tmp = new SequenceI[s.size()]; - s.copyInto(tmp); + SequenceI[] tmp = s.toArray(new SequenceI[s.size()]); sequence[pe] = tmp; if (c.size() > 0) { - String[] tch = new String[c.size()]; - c.copyInto(tch); + String[] tch = c.toArray(new String[c.size()]); for (int i = 0; i < tch.length; i++) { if (tch[i] == nullChain)