X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fproject%2FJalview2XML.java;h=4cfac7bf5dcb843c06f467990c46261c7e769fa5;hb=4f30214e8098748469c6a4269ac2ed6c5750e4b0;hp=6340e64eb3a88a2c140e1147a81bcefc6dc72fa1;hpb=0bc9297afd18a3e2b412364bf1af426570555b9a;p=jalview.git diff --git a/src/jalview/project/Jalview2XML.java b/src/jalview/project/Jalview2XML.java index 6340e64..4cfac7b 100644 --- a/src/jalview/project/Jalview2XML.java +++ b/src/jalview/project/Jalview2XML.java @@ -24,6 +24,56 @@ import static jalview.math.RotatableMatrix.Axis.X; import static jalview.math.RotatableMatrix.Axis.Y; import static jalview.math.RotatableMatrix.Axis.Z; +import java.awt.Color; +import java.awt.Font; +import java.awt.Rectangle; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.lang.reflect.InvocationTargetException; +import java.math.BigInteger; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Enumeration; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.IdentityHashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.Vector; +import java.util.jar.JarEntry; +import java.util.jar.JarInputStream; +import java.util.jar.JarOutputStream; + +import javax.swing.JInternalFrame; +import javax.swing.SwingUtilities; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.Marshaller; +import javax.xml.datatype.DatatypeConfigurationException; +import javax.xml.datatype.DatatypeFactory; +import javax.xml.datatype.XMLGregorianCalendar; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamReader; + import jalview.analysis.Conservation; import jalview.analysis.PCA; import jalview.analysis.scoremodels.ScoreModels; @@ -53,17 +103,21 @@ import jalview.datamodel.features.FeatureMatcher; import jalview.datamodel.features.FeatureMatcherI; import jalview.datamodel.features.FeatureMatcherSet; import jalview.datamodel.features.FeatureMatcherSetI; +import jalview.ext.rbvi.chimera.JalviewChimeraBinding; import jalview.ext.varna.RnaModel; import jalview.gui.AlignFrame; import jalview.gui.AlignViewport; import jalview.gui.AlignmentPanel; import jalview.gui.AppVarna; import jalview.gui.ChimeraViewFrame; +import jalview.gui.ChimeraXViewFrame; import jalview.gui.Desktop; +import jalview.gui.JalviewChimeraXBindingModel; import jalview.gui.JvOptionPane; import jalview.gui.OOMWarning; import jalview.gui.PCAPanel; import jalview.gui.PaintRefresher; +import jalview.gui.PymolViewer; import jalview.gui.SplitFrame; import jalview.gui.StructureViewer; import jalview.gui.StructureViewer.ViewerType; @@ -150,55 +204,6 @@ import jalview.xml.binding.jalview.SequenceSet.SequenceSetProperties; import jalview.xml.binding.jalview.ThresholdType; import jalview.xml.binding.jalview.VAMSAS; -import java.awt.Color; -import java.awt.Font; -import java.awt.Rectangle; -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.lang.reflect.InvocationTargetException; -import java.math.BigInteger; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Enumeration; -import java.util.GregorianCalendar; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Hashtable; -import java.util.IdentityHashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.Vector; -import java.util.jar.JarEntry; -import java.util.jar.JarInputStream; -import java.util.jar.JarOutputStream; - -import javax.swing.JInternalFrame; -import javax.swing.SwingUtilities; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBElement; -import javax.xml.bind.Marshaller; -import javax.xml.datatype.DatatypeConfigurationException; -import javax.xml.datatype.DatatypeFactory; -import javax.xml.datatype.XMLGregorianCalendar; -import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.XMLStreamReader; - /** * Write out the current jalview desktop state as a Jalview XML stream. * @@ -1099,15 +1104,17 @@ public class Jalview2XML if (!storeDS && !viewIds.contains(viewId)) { viewIds.add(viewId); - try + File viewerState = viewFrame.saveSession(); + if (viewerState != null) { - String viewerState = viewFrame.getStateInfo(); - writeJarEntry(jout, getViewerJarEntryName(viewId), - viewerState.getBytes()); - } catch (IOException e) + copyFileToJar(jout, viewerState.getPath(), + getViewerJarEntryName(viewId)); + } + else { - System.err.println( - "Error saving viewer state: " + e.getMessage()); + Cache.log.error("Failed to save viewer state for " + + + viewFrame.getViewerType().toString()); } } } @@ -2005,32 +2012,23 @@ public class Jalview2XML protected void copyFileToJar(JarOutputStream jout, String infilePath, String jarEntryName) { - DataInputStream dis = null; - try + try (InputStream is = new FileInputStream(infilePath)) { File file = new File(infilePath); if (file.exists() && jout != null) { - dis = new DataInputStream(new FileInputStream(file)); - byte[] data = new byte[(int) file.length()]; - dis.readFully(data); - writeJarEntry(jout, jarEntryName, data); + System.out.println("Writing jar entry " + jarEntryName); + jout.putNextEntry(new JarEntry(jarEntryName)); + copyAll(is, jout); + jout.closeEntry(); + // dis = new DataInputStream(new FileInputStream(file)); + // byte[] data = new byte[(int) file.length()]; + // dis.readFully(data); + // writeJarEntry(jout, jarEntryName, data); } } catch (Exception ex) { ex.printStackTrace(); - } finally - { - if (dis != null) - { - try - { - dis.close(); - } catch (IOException e) - { - // ignore - } - } } } @@ -2058,6 +2056,24 @@ public class Jalview2XML } /** + * Copies input to output, in 4K buffers; handles any data (text or binary) + * + * @param in + * @param out + * @throws IOException + */ + protected void copyAll(InputStream in, OutputStream out) + throws IOException + { + byte[] buffer = new byte[4096]; + int bytesRead = 0; + while ((bytesRead = in.read(buffer)) != -1) + { + out.write(buffer, 0, bytesRead); + } + } + + /** * Save the state of a structure viewer * * @param ap @@ -2124,7 +2140,7 @@ public class Jalview2XML final String viewId = viewFrame.getViewId(); state.setViewId(viewId); state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap)); - state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap)); + state.setColourwithAlignPanel(viewFrame.isUsedForColourBy(ap)); state.setColourByJmol(viewFrame.isColouredByViewer()); state.setType(viewFrame.getViewerType().toString()); // pdb.addStructureState(state); @@ -3185,8 +3201,6 @@ public class Jalview2XML protected String copyJarEntry(jarInputStreamProvider jprovider, String jarEntryName, String prefix, String suffixModel) { - BufferedReader in = null; - PrintWriter out = null; String suffix = ".tmp"; if (suffixModel == null) { @@ -3197,33 +3211,24 @@ public class Jalview2XML { suffix = "." + suffixModel.substring(sfpos + 1); } - try - { - JarInputStream jin = jprovider.getJarInputStream(); - /* - * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new - * URL(jprovider).openStream()); } else { jin = new JarInputStream(new - * FileInputStream(jprovider)); } - */ + try (JarInputStream jin = jprovider.getJarInputStream()) + { JarEntry entry = null; do { entry = jin.getNextJarEntry(); } while (entry != null && !entry.getName().equals(jarEntryName)); + if (entry != null) { - in = new BufferedReader(new InputStreamReader(jin, UTF_8)); + // in = new BufferedReader(new InputStreamReader(jin, UTF_8)); File outFile = File.createTempFile(prefix, suffix); outFile.deleteOnExit(); - out = new PrintWriter(new FileOutputStream(outFile)); - String data; - - while ((data = in.readLine()) != null) + try (OutputStream os = new FileOutputStream(outFile)) { - out.println(data); + copyAll(jin, os); } - out.flush(); String t = outFile.getAbsolutePath(); return t; } @@ -3234,22 +3239,6 @@ public class Jalview2XML } catch (Exception ex) { ex.printStackTrace(); - } finally - { - if (in != null) - { - try - { - in.close(); - } catch (IOException e) - { - // ignore - } - } - if (out != null) - { - out.close(); - } } return null; @@ -4428,29 +4417,46 @@ public class Jalview2XML * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry * "viewer_"+stateData.viewId */ - if (ViewerType.CHIMERA.toString().equals(stateData.getType())) + String type = stateData.getType(); + if (type == null) { - createChimeraViewer(viewerData, af, jprovider); + type = ViewerType.JMOL.toString(); } - else + try { - /* - * else Jmol (if pre-2.9, stateData contains JMOL state string) - */ - createJmolViewer(viewerData, af, jprovider); + ViewerType viewerType = ViewerType.valueOf(type); + switch (viewerType) + { + case CHIMERA: + createChimeraViewer(viewerData, af, jprovider, false); + break; + case CHIMERAX: + createChimeraViewer(viewerData, af, jprovider, true); + break; + case PYMOL: + createPymolViewer(viewerData, af, jprovider); + break; + case JMOL: + createJmolViewer(viewerData, af, jprovider); + } + } catch (IllegalArgumentException | NullPointerException e) + { + Cache.log.error( + "Invalid structure viewer type: " + type); } } /** - * Create a new Chimera viewer. + * Create a new Chimera or ChimeraX viewer * * @param data * @param af * @param jprovider + * @param isChimeraX */ protected void createChimeraViewer( Entry viewerData, AlignFrame af, - jarInputStreamProvider jprovider) + jarInputStreamProvider jprovider, boolean isChimeraX) { StructureViewerModel data = viewerData.getValue(); String chimeraSessionFile = data.getStateData(); @@ -4462,8 +4468,11 @@ public class Jalview2XML * 'uniquified' sviewid used to reconstruct the viewer here */ String viewerJarEntryName = getViewerJarEntryName(data.getViewId()); + String extension = isChimeraX + ? JalviewChimeraXBindingModel.CHIMERAX_SESSION_EXTENSION + : JalviewChimeraBinding.CHIMERA_SESSION_EXTENSION; chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName, - "chimera", ".py"); + "chimera", extension); Set> fileData = data.getFileData() .entrySet(); @@ -4489,9 +4498,13 @@ public class Jalview2XML .toArray(new SequenceI[allseqs.size()][]); String newViewId = viewerData.getKey(); - ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile, - af.alignPanel, pdbArray, seqsArray, colourByChimera, - colourBySequence, newViewId); + ChimeraViewFrame cvf = isChimeraX + ? new ChimeraXViewFrame(chimeraSessionFile, af.alignPanel, + pdbArray, seqsArray, colourByChimera, colourBySequence, + newViewId) + : new ChimeraViewFrame(chimeraSessionFile, af.alignPanel, + pdbArray, seqsArray, colourByChimera, colourBySequence, + newViewId); cvf.setSize(data.getWidth(), data.getHeight()); cvf.setLocation(data.getX(), data.getY()); } @@ -6360,6 +6373,61 @@ public class Jalview2XML } /** + * Create a new PyMol viewer + * + * @param data + * @param af + * @param jprovider + */ + protected void createPymolViewer( + Entry viewerData, AlignFrame af, + jarInputStreamProvider jprovider) + { + StructureViewerModel data = viewerData.getValue(); + String pymolSessionFile = data.getStateData(); + + /* + * Copy PyMol session from jar entry "viewer_"+viewId to a temporary file + * + * NB this is the 'saved' viewId as in the project file XML, _not_ the + * 'uniquified' sviewid used to reconstruct the viewer here + */ + String viewerJarEntryName = getViewerJarEntryName(data.getViewId()); + pymolSessionFile = copyJarEntry(jprovider, viewerJarEntryName, + "pymol", ".pse"); + + Set> fileData = data.getFileData() + .entrySet(); + List pdbs = new ArrayList<>(); + List allseqs = new ArrayList<>(); + for (Entry pdb : fileData) + { + String filePath = pdb.getValue().getFilePath(); + String pdbId = pdb.getValue().getPdbId(); + // pdbs.add(new PDBEntry(filePath, pdbId)); + pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath)); + final List seqList = pdb.getValue().getSeqList(); + SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]); + allseqs.add(seqs); + } + + boolean colourByPymol = data.isColourByViewer(); + boolean colourBySequence = data.isColourWithAlignPanel(); + + // TODO use StructureViewer as a factory here, see JAL-1761 + final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]); + final SequenceI[][] seqsArray = allseqs + .toArray(new SequenceI[allseqs.size()][]); + String newViewId = viewerData.getKey(); + + PymolViewer pv = new PymolViewer(pymolSessionFile, + af.alignPanel, pdbArray, seqsArray, colourByPymol, + colourBySequence, newViewId); + pv.setSize(data.getWidth(), data.getHeight()); + pv.setLocation(data.getX(), data.getY()); + } + + /** * Populates an XML model of the feature colour scheme for one feature type * * @param featureType