/* VARNA is a tool for the automated drawing, visualization and annotation of the secondary structure of RNA, designed as a companion software for web servers and databases. Copyright (C) 2008 Kevin Darty, Alain Denise and Yann Ponty. electronic mail : Yann.Ponty@lri.fr paper mail : LRI, bat 490 University Paris-Sud 91405 Orsay Cedex France This file is part of VARNA version 3.1. VARNA version 3.1 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. VARNA version 3.1 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 VARNA version 3.1. If not, see http://www.gnu.org/licenses. */ package fr.orsay.lri.varna.applications; import java.awt.Graphics2D; import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Comparator; import java.util.Hashtable; import java.util.Vector; import javax.imageio.IIOImage; import javax.imageio.ImageIO; import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; import javax.imageio.stream.FileImageOutputStream; import fr.orsay.lri.varna.VARNAPanel; import fr.orsay.lri.varna.exceptions.ExceptionExportFailed; import fr.orsay.lri.varna.exceptions.ExceptionFileFormatOrSyntax; import fr.orsay.lri.varna.exceptions.ExceptionJPEGEncoding; import fr.orsay.lri.varna.exceptions.ExceptionLoadingFailed; import fr.orsay.lri.varna.exceptions.ExceptionModeleStyleBaseSyntaxError; import fr.orsay.lri.varna.exceptions.ExceptionNonEqualLength; import fr.orsay.lri.varna.exceptions.ExceptionParameterError; import fr.orsay.lri.varna.exceptions.ExceptionPermissionDenied; import fr.orsay.lri.varna.exceptions.ExceptionUnmatchedClosingParentheses; import fr.orsay.lri.varna.exceptions.ExceptionWritingForbidden; import fr.orsay.lri.varna.factories.RNAFactory; import fr.orsay.lri.varna.interfaces.InterfaceParameterLoader; import fr.orsay.lri.varna.models.VARNAConfig; import fr.orsay.lri.varna.models.VARNAConfigLoader; import fr.orsay.lri.varna.models.rna.RNA; public class VARNAcmd implements InterfaceParameterLoader { public class ExitCode extends Exception{ /** * */ private static final long serialVersionUID = -3011196062868355584L; private int _c; private String _msg; public ExitCode(int c,String msg){ _c = c; _msg = msg; } public int getExitCode(){ return _c; } public String getExitMessage(){ return _msg; } } private Hashtable<String, String> _optsValues = new Hashtable<String, String>(); private Hashtable<String, String> _basicOptsInv = new Hashtable<String, String>(); private String _inFile = ""; private String _outFile = ""; int _baseWidth = 400; double _scale = 1.0; float _quality = 0.9f; private String[] _basicOptions = { VARNAConfigLoader.algoOpt, VARNAConfigLoader.bpStyleOpt, VARNAConfigLoader.bondColorOpt, VARNAConfigLoader.backboneColorOpt, VARNAConfigLoader.periodNumOpt, VARNAConfigLoader.baseInnerColorOpt, VARNAConfigLoader.baseOutlineColorOpt, }; public VARNAcmd(Vector<String> args) throws ExitCode { for (int j = 0; j < _basicOptions.length; j++) { _basicOptsInv.put(_basicOptions[j], _basicOptions[j]); } int i = 0; while (i < args.size()) { String opt = args.elementAt(i); if (opt.charAt(0) != '-') { errorExit("Missing or unknown option \"" + opt + "\""); } if (opt.equals("-h")) { displayLightHelpExit(); } if (opt.equals("-x")) { displayDetailledHelpExit(); } else { if (i + 1 >= args.size()) { errorExit("Missing argument for option \"" + opt + "\""); } String val = args.get(i + 1); if (opt.equals("-i")) { _inFile = val; } else if (opt.equals("-o")) { _outFile = val; } else if (opt.equals("-quality")) { _quality = Float.parseFloat(val); } else if (opt.equals("-resolution")) { _scale = Float.parseFloat(val); } else { addOption(opt, val); } } i += 2; } if (_outFile.equals("")) { errorExit("Missing output file"); } } public void addOption(String key, String value) { if (key.equals("-i")) { _inFile = value; } else if (key.equals("-o")) { _outFile = value; } else { _optsValues.put(key.substring(1), value); } } private String getDescription() { return "VARNA v" + VARNAConfig.MAJOR_VERSION + "." + VARNAConfig.MINOR_VERSION + " Assisted drawing of RNA secondary structure (Command Line version)"; } private String indent(int k) { String result = ""; for (int i = 0; i < k; i++) { result += " "; } return result; } private String complete(String s, int k) { String result = s; while (result.length() < k) { result += " "; } return result; } Vector<String[]> matrix = new Vector<String[]>(); private void addLine(String opt, String val) { String[] line = { opt, val }; matrix.add(line); } private static int MAX_WIDTH = 100; @SuppressWarnings("unchecked") private void printMatrix(int ind) { String[][] values = new String[matrix.size()][]; matrix.toArray(values); Arrays.sort(values, new Comparator() { public int compare(Object o1, Object o2) { String[] tab1 = (String[]) o1; String[] tab2 = (String[]) o2; return tab1[0].compareTo(tab2[0]); } }); int maxSize = 0; for (int i = 0; i < values.length; i++) { String[] elem = values[i]; maxSize = Math.max(maxSize, elem[0].length()); } maxSize += ind + 2; for (int i = 0; i < values.length; i++) { String[] elem = values[i]; String opt = elem[0]; String msg = elem[1]; opt = complete("", ind) + "-" + complete(opt, maxSize - ind); System.out.println(opt + msg.substring(0, Math.min(MAX_WIDTH - opt.length(), msg.length()))); if (opt.length() + msg.length() >= MAX_WIDTH) { int off = MAX_WIDTH - opt.length(); while (off < msg.length()) { String nmsg = msg.substring(off, Math.min(off + MAX_WIDTH - opt.length(), msg.length())); System.out.println(complete("", opt.length())+nmsg); off += MAX_WIDTH - opt.length(); } } } matrix = new Vector<String[]>(); } private void printUsage() { System.out .println("Usage: java -cp . [-i InFile|-sequenceDBN XXX -structureDBN YYY] -o OutFile [Options]"); System.out.println("Where:"); System.out.println(indent(1) + "OutFile\tSupported formats: {JPEG,PNG,EPS,XFIG,SVG}"); System.out .println(indent(1) + "InFile\tSecondary structure file: Supported formats: {BPSEQ,CT,RNAML,DBN}"); } private void printHelpOptions() { System.out.println("\nMain options:"); addLine("h", "Displays a short description of main options and exits"); addLine("x", "Displays a detailled description of all options"); printMatrix(2); } private void printMainOptions(String[][] info) { System.out.println("\nMain options:"); addLine("h", "Displays a short description of main options and exits"); addLine("x", "Displays a detailled description of all options"); for (int i = 0; i < info.length; i++) { String key = info[i][0]; if (_basicOptsInv.containsKey(key)) { addLine(key, info[i][2]); } } printMatrix(2); } private void printAdvancedOptions(String[][] info) { System.out.println("\nAdvanced options:"); for (int i = 0; i < info.length; i++) { String key = info[i][0]; if (!_basicOptsInv.containsKey(key)) { addLine(key, info[i][2]); } } addLine("quality", "Sets quality (non-vector file formats only)"); addLine("resolution", "Sets resolution (non-vector file formats only)"); printMatrix(2); } private void displayLightHelpExit() throws ExitCode { String[][] info = VARNAConfigLoader.getParameterInfo(); System.out.println(getDescription()); printUsage(); printMainOptions(info); throw(new ExitCode(1,"")); } private void displayDetailledHelpExit() throws ExitCode { String[][] info = VARNAConfigLoader.getParameterInfo(); System.out.println(getDescription()); printUsage(); printMainOptions(info); printAdvancedOptions(info); throw(new ExitCode(1,"")); } private void errorExit(String msg) throws ExitCode { System.out.println(getDescription()); System.out.println("Error: " + msg + "\n"); printUsage(); printHelpOptions(); throw(new ExitCode(1,"")); } public String getParameterValue(String key, String def) { if (_optsValues.containsKey(key)) { return _optsValues.get(key); } return def; } public String formatOutputPath(String base,int index, int total) { String result = base; if (total>1) { int indexDot = base.lastIndexOf('.'); String pref; String ext; if (indexDot!=-1) { pref = base.substring(0,indexDot); ext = base.substring(indexDot); } else{ pref=base; ext=""; } result = pref+"-"+index+ext; } System.err.println("Output file: "+result); return result; } public void run() throws IOException, ExitCode { VARNAConfigLoader VARNAcfg = new VARNAConfigLoader(this); ArrayList<VARNAPanel> vpl; try { Collection<RNA> rnas; if (!_inFile.equals("")) { rnas = RNAFactory.loadSecStr(_inFile); if (rnas.isEmpty()) { throw new ExceptionFileFormatOrSyntax("No RNA could be parsed from file '"+_inFile+"'."); } } else { RNA r = new RNA(); r.setRNA(this.getParameterValue("sequenceDBN", ""), this.getParameterValue( "structureDBN", "")); rnas = new ArrayList<RNA>(); rnas.add(r); } int index = 1; for (RNA r: rnas) { VARNAcfg.setRNA(r); vpl = VARNAcfg.createVARNAPanels(); if (vpl.size() > 0) { VARNAPanel _vp = vpl.get(0); RNA _rna = _vp.getRNA(); Rectangle2D.Double bbox = _vp.getRNA().getBBox(); //System.out.println(_vp.getRNA().getBBox()); if (_outFile.toLowerCase().endsWith(".jpeg") || _outFile.toLowerCase().endsWith(".jpg") || _outFile.toLowerCase().endsWith(".png")) { _vp.setTitleFontSize((int)(_scale*_vp.getTitleFont().getSize())); _vp.setSize((int)(_baseWidth*_scale), (int)((_scale*_baseWidth*bbox.height)/((double)bbox.width))); } if (_outFile.toLowerCase().endsWith(".eps")) { _rna.saveRNAEPS(formatOutputPath(_outFile,index, rnas.size()), _vp.getConfig()); } else if (_outFile.toLowerCase().endsWith(".xfig") || _outFile.toLowerCase().endsWith(".fig")) { _rna.saveRNAXFIG(formatOutputPath(_outFile,index, rnas.size()), _vp.getConfig()); } else if (_outFile.toLowerCase().endsWith(".svg")) { _rna.saveRNASVG(formatOutputPath(_outFile,index, rnas.size()), _vp.getConfig()); } else if (_outFile.toLowerCase().endsWith(".jpeg") || _outFile.toLowerCase().endsWith(".jpg")) { this.saveToJPEG(formatOutputPath(_outFile,index, rnas.size()), _vp); } else if (_outFile.toLowerCase().endsWith(".png")) { this.saveToPNG(formatOutputPath(_outFile,index, rnas.size()), _vp); } else if (_outFile.toLowerCase().endsWith(".varna")) { _vp.saveSession(formatOutputPath(_outFile,index, rnas.size())); } else { errorExit("Unknown extension for output file \"" + _outFile + "\""); } } index++; } } catch (ExceptionWritingForbidden e) { e.printStackTrace(); throw(new ExitCode(1,"")); } catch (ExceptionJPEGEncoding e) { e.printStackTrace(); throw(new ExitCode(1,"")); } catch (ExceptionParameterError e) { e.printStackTrace(); throw(new ExitCode(1,"")); } catch (ExceptionModeleStyleBaseSyntaxError e) { e.printStackTrace(); throw(new ExitCode(1,"")); } catch (ExceptionNonEqualLength e) { e.printStackTrace(); throw(new ExitCode(1,"")); } catch (ExceptionUnmatchedClosingParentheses e) { e.printStackTrace(); System.exit(1); } catch (ExceptionExportFailed e) { e.printStackTrace(); throw(new ExitCode(1,"")); } catch (ExceptionPermissionDenied e) { e.printStackTrace(); throw(new ExitCode(1,"")); } catch (ExceptionLoadingFailed e) { e.printStackTrace(); throw(new ExitCode(1,"")); } catch (ExceptionFileFormatOrSyntax e) { e.setPath(_inFile); e.printStackTrace(); throw(new ExitCode(1,"")); } catch (FileNotFoundException e) { throw(new ExitCode(1,"Error: Missing input file \""+_inFile+"\".")); } throw(new ExitCode(0,"")); } public void saveToJPEG(String filename, VARNAPanel vp) throws ExceptionJPEGEncoding, ExceptionExportFailed { BufferedImage myImage = new BufferedImage((int) Math.round(vp .getWidth() ), (int) Math.round(vp.getHeight() ), BufferedImage.TYPE_INT_RGB); Graphics2D g2 = myImage.createGraphics(); vp.paintComponent(g2); try { FileImageOutputStream out = new FileImageOutputStream(new File(filename)); ImageWriter writer = ImageIO.getImageWritersByFormatName("jpeg").next(); ImageWriteParam params = writer.getDefaultWriteParam(); params.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); params.setCompressionQuality(_quality); writer.setOutput(out); IIOImage myIIOImage = new IIOImage(myImage, null, null); writer.write(null, myIIOImage, params); out.close(); } catch (IOException e) { throw new ExceptionExportFailed(e.getMessage(), filename); } } public void saveToPNG(String filename, VARNAPanel vp) throws ExceptionExportFailed { BufferedImage myImage = new BufferedImage((int) Math.round(vp .getWidth()), (int) Math.round(vp.getHeight() ), BufferedImage.TYPE_INT_RGB); Graphics2D g2 = myImage.createGraphics(); vp.paintComponent(g2); g2.dispose(); try { ImageIO.write(myImage, "PNG", new File(filename)); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] argv) { Vector<String> opts = new Vector<String>(); for (int i = 0; i < argv.length; i++) { opts.add(argv[i]); } try { VARNAcmd app = new VARNAcmd(opts); app.run(); } catch (IOException e) { e.printStackTrace(); } catch (ExitCode e) { System.err.println(e.getExitMessage()); System.exit(e.getExitCode()); } } }