JAL-3032 adds Java 8 functionality (2/2)
[jalview.git] / src2 / fr / orsay / lri / varna / applications / VARNAcmd.java
1 /*
2  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.
3  Copyright (C) 2008  Kevin Darty, Alain Denise and Yann Ponty.
4  electronic mail : Yann.Ponty@lri.fr
5  paper mail : LRI, bat 490 Université Paris-Sud 91405 Orsay Cedex France
6
7  This file is part of VARNA version 3.1.
8  VARNA version 3.1 is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License
9  as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
10
11  VARNA version 3.1 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
12  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13  See the GNU General Public License for more details.
14
15  You should have received a copy of the GNU General Public License along with VARNA version 3.1.
16  If not, see http://www.gnu.org/licenses.
17  */
18 package fr.orsay.lri.varna.applications;
19
20
21 import java.awt.Graphics2D;
22 import java.awt.geom.AffineTransform;
23 import java.awt.geom.Rectangle2D;
24 import java.awt.image.BufferedImage;
25 import java.io.File;
26 import java.io.FileInputStream;
27 import java.io.FileNotFoundException;
28 import java.io.FileOutputStream;
29 import java.io.IOException;
30 import java.io.OutputStream;
31 import java.util.ArrayList;
32 import java.util.Arrays;
33 import java.util.Collection;
34 import java.util.Comparator;
35 import java.util.Hashtable;
36 import java.util.Vector;
37
38 import javax.imageio.IIOImage;
39 import javax.imageio.ImageIO;
40 import javax.imageio.ImageWriteParam;
41 import javax.imageio.ImageWriter;
42 import javax.imageio.stream.FileImageOutputStream;
43 import javax.swing.JFrame;
44
45 import fr.orsay.lri.varna.VARNAPanel;
46 import fr.orsay.lri.varna.exceptions.ExceptionExportFailed;
47 import fr.orsay.lri.varna.exceptions.ExceptionFileFormatOrSyntax;
48 import fr.orsay.lri.varna.exceptions.ExceptionJPEGEncoding;
49 import fr.orsay.lri.varna.exceptions.ExceptionLoadingFailed;
50 import fr.orsay.lri.varna.exceptions.ExceptionModeleStyleBaseSyntaxError;
51 import fr.orsay.lri.varna.exceptions.ExceptionNonEqualLength;
52 import fr.orsay.lri.varna.exceptions.ExceptionParameterError;
53 import fr.orsay.lri.varna.exceptions.ExceptionPermissionDenied;
54 import fr.orsay.lri.varna.exceptions.ExceptionUnmatchedClosingParentheses;
55 import fr.orsay.lri.varna.exceptions.ExceptionWritingForbidden;
56 import fr.orsay.lri.varna.factories.RNAFactory;
57 import fr.orsay.lri.varna.interfaces.InterfaceParameterLoader;
58 import fr.orsay.lri.varna.models.FullBackup;
59 import fr.orsay.lri.varna.models.VARNAConfig;
60 import fr.orsay.lri.varna.models.VARNAConfigLoader;
61 import fr.orsay.lri.varna.models.rna.RNA;
62
63 public class VARNAcmd implements InterfaceParameterLoader {
64         
65         public class ExitCode extends Exception{
66                 /**
67                  * 
68                  */
69                 private static final long serialVersionUID = -3011196062868355584L;
70                 private int _c;
71                 private String _msg;
72                 public ExitCode(int c,String msg){
73                         _c = c;
74                         _msg = msg;
75                 }
76                 public int getExitCode(){
77                         return _c;
78                 }
79                 public String getExitMessage(){
80                         return _msg;
81                 }
82         }
83         
84         
85         private Hashtable<String, String> _optsValues = new Hashtable<String, String>();
86         private Hashtable<String, String> _basicOptsInv = new Hashtable<String, String>();
87         private String _inFile = "";
88         private String _outFile = "";
89         int _baseWidth = 400;
90         double _scale = 1.0;
91         float _quality = 0.9f;
92
93         private String[] _basicOptions = { VARNAConfigLoader.algoOpt,
94                         VARNAConfigLoader.bpStyleOpt, VARNAConfigLoader.bondColorOpt,
95                         VARNAConfigLoader.backboneColorOpt, VARNAConfigLoader.periodNumOpt,
96                         VARNAConfigLoader.baseInnerColorOpt,
97                         VARNAConfigLoader.baseOutlineColorOpt,
98
99         };
100
101         public VARNAcmd(Vector<String> args) throws ExitCode {
102                 for (int j = 0; j < _basicOptions.length; j++) {
103                         _basicOptsInv.put(_basicOptions[j], _basicOptions[j]);
104                 }
105                 int i = 0;
106                 while (i < args.size()) {
107                         String opt = args.elementAt(i);
108                         if (opt.charAt(0) != '-') {
109                                 errorExit("Missing or unknown option \"" + opt + "\"");
110                         }
111                         if (opt.equals("-h")) {
112                                 displayLightHelpExit();
113                         }
114                         if (opt.equals("-x")) {
115                                 displayDetailledHelpExit();
116                         } else {
117                                 if (i + 1 >= args.size()) {
118                                         errorExit("Missing argument for option \"" + opt + "\"");
119                                 }
120                                 String val = args.get(i + 1);
121                                 if (opt.equals("-i")) {
122                                         _inFile = val;
123                                 } else if (opt.equals("-o")) {
124                                         _outFile = val;
125                                 } else if (opt.equals("-quality")) {
126                                         _quality = Float.parseFloat(val);
127                                 } else if (opt.equals("-resolution")) {
128                                         _scale = Float.parseFloat(val);
129                                 } else {
130                                         addOption(opt, val);
131                                 }
132                         }
133                         i += 2;
134                 }
135         }
136
137         public void addOption(String key, String value) {
138                 if (key.equals("-i")) {
139                         _inFile = value;
140                 } else if (key.equals("-o")) {
141                         _outFile = value;
142                 } else {
143                         _optsValues.put(key.substring(1), value);
144                 }
145         }
146
147         private String getDescription() {
148                 return "VARNA v"
149                                 + VARNAConfig.MAJOR_VERSION
150                                 + "."
151                                 + VARNAConfig.MINOR_VERSION
152                                 + " Assisted drawing of RNA secondary structure (Command Line version)";
153         }
154
155         private String indent(int k) {
156                 String result = "";
157                 for (int i = 0; i < k; i++) {
158                         result += "  ";
159                 }
160                 return result;
161         }
162
163         private String complete(String s, int k) {
164                 String result = s;
165                 while (result.length() < k) {
166                         result += " ";
167                 }
168                 return result;
169         }
170
171         Vector<String[]> matrix = new Vector<String[]>();
172
173         private void addLine(String opt, String val) {
174                 String[] line = { opt, val };
175                 matrix.add(line);
176         }
177
178         private static int MAX_WIDTH = 100;
179
180         @SuppressWarnings("unchecked")
181         private void printMatrix(int ind) {
182                 String[][] values = new String[matrix.size()][];
183                 matrix.toArray(values);
184                 Arrays.sort(values, new Comparator() {
185                         public int compare(Object o1, Object o2) {
186                                 String[] tab1 = (String[]) o1;
187                                 String[] tab2 = (String[]) o2;
188                                 return tab1[0].compareTo(tab2[0]);
189                         }
190                 });
191
192                 int maxSize = 0;
193                 for (int i = 0; i < values.length; i++) {
194                         String[] elem = values[i];
195                         maxSize = Math.max(maxSize, elem[0].length());
196                 }
197                 maxSize += ind + 2;
198                 for (int i = 0; i < values.length; i++) {
199                         String[] elem = values[i];
200                         String opt = elem[0];
201                         String msg = elem[1];
202                         opt = complete("", ind) + "-" + complete(opt, maxSize - ind);
203                         System.out.println(opt  + msg.substring(0, Math.min(MAX_WIDTH - opt.length(), msg.length())));
204                         if (opt.length() + msg.length() >= MAX_WIDTH) {
205                                 int off = MAX_WIDTH - opt.length();
206                                 while (off < msg.length()) {
207                                         String nmsg = msg.substring(off, Math.min(off + MAX_WIDTH
208                                                         - opt.length(), msg.length()));
209                                         System.out.println(complete("", opt.length())+nmsg);
210                                         off += MAX_WIDTH - opt.length();
211                                 }
212                         }
213                 } 
214                 matrix = new Vector<String[]>();
215         }
216
217         private void printUsage() {
218                 System.out
219                                 .println("Usage: java -cp . [-i InFile|-sequenceDBN XXX -structureDBN YYY] -o OutFile [Options]");
220                 System.out.println("Where:");
221                 System.out.println(indent(1)
222                                 + "OutFile\tSupported formats: {JPEG,PNG,EPS,XFIG,SVG}");
223                 System.out
224                                 .println(indent(1)
225                                                 + "InFile\tSecondary structure file: Supported formats: {BPSEQ,CT,RNAML,DBN}");
226
227         }
228
229         private void printHelpOptions() {
230                 System.out.println("\nMain options:");
231                 addLine("h", "Displays a short description of main options and exits");
232                 addLine("x", "Displays a detailled description of all options");
233                 printMatrix(2);
234         }
235
236         private void printMainOptions(String[][] info) {
237                 System.out.println("\nMain options:");
238                 addLine("h", "Displays a short description of main options and exits");
239                 addLine("x", "Displays a detailled description of all options");
240                 for (int i = 0; i < info.length; i++) {
241                         String key = info[i][0];
242                         if (_basicOptsInv.containsKey(key)) {
243                                 addLine(key, info[i][2]);
244                         }
245                 }
246                 printMatrix(2);
247         }
248
249         private void printAdvancedOptions(String[][] info) {
250                 System.out.println("\nAdvanced options:");
251                 for (int i = 0; i < info.length; i++) {
252                         String key = info[i][0];
253                         if (!_basicOptsInv.containsKey(key)) {
254                                 addLine(key, info[i][2]);
255                         }
256                 }
257                 addLine("quality", "Sets quality (non-vector file formats only)");
258                 addLine("resolution", "Sets resolution (non-vector file formats only)");
259                 printMatrix(2);
260         }
261
262         private void displayLightHelpExit() throws ExitCode {
263                 String[][] info = VARNAConfigLoader.getParameterInfo();
264                 System.out.println(getDescription());
265                 printUsage();
266                 printMainOptions(info);
267                 throw(new ExitCode(1,""));
268         }
269
270         private void displayDetailledHelpExit() throws ExitCode {
271                 String[][] info = VARNAConfigLoader.getParameterInfo();
272                 System.out.println(getDescription());
273                 printUsage();
274                 printMainOptions(info);
275                 printAdvancedOptions(info);
276                 throw(new ExitCode(1,""));
277         }
278
279         private void errorExit(String msg) throws ExitCode {
280                 System.out.println(getDescription());
281                 System.out.println("Error: " + msg + "\n");
282                 printUsage();
283                 printHelpOptions();
284                 throw(new ExitCode(1,""));
285         }
286
287         public String getParameterValue(String key, String def) {
288                 if (_optsValues.containsKey(key)) {
289                         return _optsValues.get(key);
290                 }
291                 return def;
292         }
293
294         public String formatOutputPath(String base,int index, int total)
295         {
296                 String result = base;
297                 
298                 if (total>1)
299                 {
300                         int indexDot = base.lastIndexOf('.');
301                         String pref;
302                         String ext;
303                         if (indexDot!=-1)
304                         {
305                           pref = base.substring(0,indexDot);
306                           ext = base.substring(indexDot);
307                         }
308                         else{
309                                 pref=base;
310                                 ext="";
311                         }
312                         result = pref+"-"+index+ext;
313                 }
314                 System.err.println("Output file: "+result);
315                 return result;
316         }
317         
318         public void run() throws IOException, ExitCode {
319                 VARNAConfigLoader VARNAcfg = new VARNAConfigLoader(this);
320                 ArrayList<VARNAPanel> vpl;
321                 ArrayList<FullBackup> confs = new ArrayList<FullBackup>();
322                 try {
323                         if (!_inFile.equals("")) {
324                                 if (!_inFile.toLowerCase().endsWith(".varna")) {
325                                         Collection<RNA> rnas = RNAFactory.loadSecStr(_inFile);
326                                          if (rnas.isEmpty())
327                                          {
328                                                  FullBackup f = null;
329                                                                 try{
330                                                                 f = VARNAPanel.importSession(new FileInputStream(_inFile), _inFile);
331                                                                 confs.add(f);
332                                                                 }
333                                                                 catch(Exception e)
334                                                                 {
335                                                                         e.printStackTrace();
336                                                                 }
337                                                 if (f==null)
338                                                 {
339                                                  throw new ExceptionFileFormatOrSyntax("No RNA could be parsed from file '"+_inFile+"'.");
340                                                 }
341                                          }
342                                          else{
343                                                  for (RNA r: rnas)
344                                                  {
345                                                          confs.add(new FullBackup(r,_inFile));
346                                                  }
347                                          }
348                                 }
349                                 else{
350                                         confs.add(VARNAPanel.importSession(_inFile));
351                                 }
352                         } else {
353                                 RNA r = new RNA();
354                                 r.setRNA(this.getParameterValue("sequenceDBN",
355                                                 ""), this.getParameterValue(
356                                                 "structureDBN", ""));
357                                 confs.add(new FullBackup(r,"From Params"));
358                         }
359                         if (!_outFile.equals(""))
360                         {
361                         int index = 1;
362                         for (FullBackup r: confs)
363                         {
364                                 VARNAcfg.setRNA(r.rna);
365                                 vpl = VARNAcfg.createVARNAPanels();
366                                 if (vpl.size() > 0) {
367                                 VARNAPanel _vp = vpl.get(0);
368                                 if (r.hasConfig())
369                                 {
370                                         _vp.setConfig(r.config);
371                                 }
372                                 RNA _rna = _vp.getRNA();
373                                 Rectangle2D.Double bbox = _vp.getRNA().getBBox();
374                                 //System.out.println(_vp.getRNA().getBBox());
375                                 
376                                 if (_outFile.toLowerCase().endsWith(".jpeg")
377                                                 || _outFile.toLowerCase().endsWith(".jpg")
378                                                 || _outFile.toLowerCase().endsWith(".png"))
379                                 { 
380                                         _vp.setTitleFontSize((int)(_scale*_vp.getTitleFont().getSize())); 
381                                     _vp.setSize((int)(_baseWidth*_scale), (int)((_scale*_baseWidth*bbox.height)/((double)bbox.width)));
382                                 }
383                                 
384                                 if (_outFile.toLowerCase().endsWith(".eps")) {
385                                         _rna.saveRNAEPS(formatOutputPath(_outFile,index, confs.size()), _vp.getConfig());
386                                 } else if (_outFile.toLowerCase().endsWith(".xfig")
387                                                 || _outFile.toLowerCase().endsWith(".fig")) {
388                                         _rna.saveRNAXFIG(formatOutputPath(_outFile,index, confs.size()), _vp.getConfig());
389                                 } else if (_outFile.toLowerCase().endsWith(".svg")) {
390                                         _rna.saveRNASVG(formatOutputPath(_outFile,index, confs.size()), _vp.getConfig());
391                                 } else if (_outFile.toLowerCase().endsWith(".jpeg")
392                                                 || _outFile.toLowerCase().endsWith(".jpg")) {
393                                         this.saveToJPEG(formatOutputPath(_outFile,index, confs.size()), _vp);
394                                 } else if (_outFile.toLowerCase().endsWith(".png")) {
395                                         this.saveToPNG(formatOutputPath(_outFile,index, confs.size()), _vp);
396                                 } else if (_outFile.toLowerCase().endsWith(".varna")) {
397                                         _vp.saveSession(formatOutputPath(_outFile,index, confs.size()));
398                                 } else {
399                                         errorExit("Unknown extension for output file \"" + _outFile
400                                                         + "\"");
401                                 }
402                         }
403                         index++;
404                         }
405                         }
406                         // No output file => Open GUI
407                         else
408                         {
409                                 VARNAGUI d = new VARNAGUI();
410                                 d.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
411                                 d.pack();
412                                 d.setVisible(true);
413                                 for (FullBackup b: confs)
414                                 {
415                                         RNA r = b.rna;
416                                         VARNAcfg.setRNA(r);
417                                         vpl = VARNAcfg.createVARNAPanels();
418                                         if (vpl.size() > 0) {
419                                                 VARNAPanel _vp = vpl.get(0);
420                                                 VARNAConfig cfg = _vp.getConfig();
421                                                 if (b.hasConfig())
422                                                 {
423                                                         cfg = b.config;
424                                                 }
425                                                 RNA rna = _vp.getRNA();
426                                                 d.addRNA(rna, cfg);
427                                                 
428                                         }
429                                 }
430                         }
431                 } catch (ExceptionWritingForbidden e) {
432                         e.printStackTrace();
433                         throw(new ExitCode(1,""));
434                 } catch (ExceptionJPEGEncoding e) {
435                         e.printStackTrace();
436                         throw(new ExitCode(1,""));
437                 } catch (ExceptionParameterError e) {
438                         e.printStackTrace();
439                         throw(new ExitCode(1,""));
440                 } catch (ExceptionModeleStyleBaseSyntaxError e) {
441                         e.printStackTrace();
442                         throw(new ExitCode(1,""));
443                 } catch (ExceptionNonEqualLength e) {
444                         e.printStackTrace();
445                         throw(new ExitCode(1,""));
446                 } catch (ExceptionUnmatchedClosingParentheses e) {
447                         e.printStackTrace();
448                         System.exit(1);
449                 } catch (ExceptionExportFailed e) {
450                         e.printStackTrace();
451                         throw(new ExitCode(1,""));
452                 } catch (ExceptionPermissionDenied e) {
453                         e.printStackTrace();
454                         throw(new ExitCode(1,""));
455                 } catch (ExceptionLoadingFailed e) {
456                         e.printStackTrace();
457                         throw(new ExitCode(1,""));
458                 } catch (ExceptionFileFormatOrSyntax e) {
459                         e.setPath(_inFile);
460                         e.printStackTrace();
461                         throw(new ExitCode(1,""));
462                 } catch (FileNotFoundException e) {
463                         throw(new ExitCode(1,"Error: Missing input file \""+_inFile+"\"."));
464                 }
465                 
466                 if (!_outFile.equals(""))
467                         throw(new ExitCode(0,""));
468                 
469                 
470         
471         }
472
473         public void saveToJPEG(String filename, VARNAPanel vp)
474                         throws ExceptionJPEGEncoding, ExceptionExportFailed {
475                 
476                 BufferedImage myImage = new BufferedImage((int) Math.round(vp
477                                 .getWidth()
478                                 ), (int) Math.round(vp.getHeight() ),
479                                 BufferedImage.TYPE_INT_RGB);
480                 Graphics2D g2 = myImage.createGraphics();
481                 vp.paintComponent(g2);
482                 try {
483                         FileImageOutputStream out = new FileImageOutputStream(new File(filename));
484                         ImageWriter writer = ImageIO.getImageWritersByFormatName("jpeg").next();
485                         ImageWriteParam params = writer.getDefaultWriteParam();
486                         params.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
487                         params.setCompressionQuality(_quality);
488                         writer.setOutput(out);
489                         IIOImage myIIOImage = new IIOImage(myImage, null, null);
490                         writer.write(null, myIIOImage, params);
491                         out.close();
492                 } catch (IOException e) {
493                         throw new ExceptionExportFailed(e.getMessage(), filename);
494                 }
495
496         }
497
498         public void saveToPNG(String filename, VARNAPanel vp)
499                         throws ExceptionExportFailed {
500                 BufferedImage myImage = new BufferedImage((int) Math.round(vp
501                                 .getWidth()), (int) Math.round(vp.getHeight() ),
502                                 BufferedImage.TYPE_INT_RGB);
503                 Graphics2D g2 = myImage.createGraphics();
504                 vp.paintComponent(g2);
505                 g2.dispose();
506                 try {
507                         ImageIO.write(myImage, "PNG", new File(filename));
508                 } catch (IOException e) {
509                         e.printStackTrace();
510                 }
511         }
512
513         public static void main(String[] argv) {
514                 Vector<String> opts = new Vector<String>();
515                 for (int i = 0; i < argv.length; i++) {
516                         opts.add(argv[i]);
517                 }
518                 try {
519                         VARNAcmd app = new VARNAcmd(opts);
520                         app.run();
521                 } catch (IOException e) {
522                         e.printStackTrace();
523                 } catch (ExitCode e) {
524                         System.err.println(e.getExitMessage());
525                         System.exit(e.getExitCode());
526                 }
527         }
528
529 }