001package org.biopax.paxtools;
002import org.apache.commons.logging.Log;
003import org.apache.commons.logging.LogFactory;
004import org.biopax.paxtools.controller.*;
005import org.biopax.paxtools.converter.LevelUpgrader;
006import org.biopax.paxtools.converter.psi.PsiToBiopax3Converter;
007import org.biopax.paxtools.io.*;
008import org.biopax.paxtools.io.gsea.GSEAConverter;
009import org.biopax.paxtools.io.sbgn.L3ToSBGNPDConverter;
010import org.biopax.paxtools.model.*;
011import org.biopax.paxtools.model.level2.entity;
012import org.biopax.paxtools.model.level3.*;
013import org.biopax.paxtools.pattern.miner.*;
014import org.biopax.paxtools.pattern.util.Blacklist;
015import org.biopax.paxtools.query.QueryExecuter;
016import org.biopax.paxtools.query.algorithm.Direction;
017import org.biopax.paxtools.client.BiopaxValidatorClient;
018import org.biopax.paxtools.client.BiopaxValidatorClient.RetFormat;
019import org.biopax.validator.jaxb.Behavior;
020
021import java.io.*;
022import java.lang.reflect.InvocationTargetException;
023import java.lang.reflect.Method;
024import java.util.*;
025import java.util.zip.GZIPInputStream;
026
027/**
028 * A command line accessible utility for basic Paxtools operations.
029 */
030public class PaxtoolsMain {
031
032    public static Log log = LogFactory.getLog(PaxtoolsMain.class);
033    private static SimpleIOHandler io = new SimpleIOHandler();
034
035    public static void main(String[] argv) throws IOException, 
036    InvocationTargetException, IllegalAccessException 
037    {
038        io.mergeDuplicates(true);
039        if (argv.length == 0) {
040            help();
041        } else {
042                String command = argv[0];
043                if(command.startsWith("--"))  //accept both w and w/out --
044                        command = command.substring(2);
045                Command.valueOf(command).run(argv);
046        }
047    }
048
049    public static void toGSEA(String[] argv) throws IOException
050    {
051        Model model = io.convertFromOWL(getInputStream(argv[1]));
052                GSEAConverter gseaConverter; //to be initialized below
053
054        boolean specCheckEnabled = (argv.length>4) && Boolean.parseBoolean(argv[4]);
055
056                if(argv.length < 6 || argv[5].equalsIgnoreCase("false")) {
057                        log.info("Collecting proteins for a pathway, the converter will also consider " +
058                                        "its sub-pathways, their sub-pathways, etc.");
059                        gseaConverter = new GSEAConverter(argv[3], specCheckEnabled);
060                } else {
061                        boolean skipAllSubPathways = Boolean.parseBoolean(argv[5]);
062                        if (skipAllSubPathways) {
063                                log.info("The converter won't traverse into sub-pathways of any pathway to collect its protein IDs.");
064                                gseaConverter = new GSEAConverter(argv[3], specCheckEnabled, true);
065                        } else { //must be a list of data source URIs, or it's an error...
066                                final Set<Provenance> skipSubPathways = new HashSet<Provenance>();
067
068                                for(String uri: argv[5].split(";")) {
069                                        Provenance pro = (Provenance) model.getByID(uri);
070                                        if(pro != null) {
071                                                skipSubPathways.add(pro);
072                                                log.info("GSEA converter won't traverse into sub-pathways of pathways from the data source: "
073                                                                + uri);
074                                        } else {
075                                                log.error("No Provenance found by uri: " + uri + " (thus - ignored)");
076                                        }
077                                }
078
079                                if(skipSubPathways.isEmpty()) {
080                                        throw new IllegalArgumentException("The last arg. of the Paxtools command is bad; " +
081                                                        "no known Provenance found (if these were semicolon-separated Provenance URIs): " + argv[5]);
082                                } else {
083                                        log.info("Collecting proteins, the converter will skip sub-pathways of pathways " +
084                                                        "of the following datasources: " + skipSubPathways.toString());
085                                        gseaConverter = new GSEAConverter(argv[3], specCheckEnabled, skipSubPathways);
086                                }
087                        }
088                }
089
090                //convert and write
091                gseaConverter.writeToGSEA(model, new FileOutputStream(argv[2]));
092    }
093
094    public static void getNeighbors(String[] argv) throws IOException
095    {
096        // set strings vars
097        String in = argv[1];
098        String[] ids = argv[2].split(",");
099        String out = argv[3];
100
101        // read BioPAX from the file
102        Model model = io.convertFromOWL(getInputStream(in));
103
104        // get elements (entities)
105        Set<BioPAXElement> elements = new HashSet<BioPAXElement>();
106        for (Object id : ids) {
107            BioPAXElement e = model.getByID(id.toString());
108            if (e != null && (e instanceof Entity || e instanceof entity)) {
109                elements.add(e);
110            } else {
111                log.warn("Source element not found: " + id);
112            }
113        }
114
115        // execute the 'nearest neighborhood' query
116        Set<BioPAXElement> result = QueryExecuter
117                        .runNeighborhood(elements, model, 1, Direction.BOTHSTREAM);
118
119        // auto-complete/clone the results in a new model
120        // (this also cuts some less important edges, right?..)
121        Completer c = new Completer(io.getEditorMap());
122        result = c.complete(result, model);
123        Cloner cln = new Cloner(io.getEditorMap(), io.getFactory());
124        model = cln.clone(model, result); // new sub-model
125
126        if (model != null) {
127            log.info("Elements in the result model: " + model.getObjects().size());
128            // export to OWL
129            io.convertToOWL(model, new FileOutputStream(out));
130        } else {
131            log.error("NULL model returned.");
132        }
133    }
134
135    public static void fetch(String[] argv) throws IOException {
136
137        // set strings vars
138        String in = argv[1];
139        String[] uris = argv[2].split(",");
140        String out = argv[3];
141
142        Model model = io.convertFromOWL(getInputStream(in));
143        io.setFactory(model.getLevel().getDefaultFactory());
144        // extract and save the sub-model (defined by ids)
145        io.convertToOWL(model, new FileOutputStream(out), uris);
146    }
147
148    
149    /*
150     * Detects and converts a BioPAX Level 1, 2,
151     * or PSI-MI/MITAB model to BioPAX Level3.
152     * 
153     * (-Dpaxtools.converter.psi.interaction=complex
154     * java option can be used to generate Complex 
155     * instead of MolecularInteraction entities from PSI interactions).
156     */
157    public static void toLevel3(String[] argv) throws IOException {
158        final String input = argv[1];
159        final String output = argv[2];
160        InputStream is = getInputStream(input);
161        FileOutputStream os = new FileOutputStream(output);
162        
163        boolean forcePsiInteractionToComplex = false;
164        String val = System.getProperty("paxtools.converter.psi.interaction");
165        if("complex".equalsIgnoreCase(val))
166                forcePsiInteractionToComplex = true;            
167        Type type = detect(input);
168
169        try {
170                switch (type) {
171
172                case BIOPAX:
173                        Model model = io.convertFromOWL(is);
174                        model = (new LevelUpgrader()).filter(model);
175                        if (model != null) {
176                                io.setFactory(model.getLevel().getDefaultFactory());
177                                io.convertToOWL(model, os); //os is closed already
178                        }
179                        break;
180
181                case PSIMI:
182                        PsiToBiopax3Converter psimiConverter = new PsiToBiopax3Converter();
183                        psimiConverter.convert(is, os, forcePsiInteractionToComplex);
184                        os.close();
185                        break;
186
187                default: //MITAB
188                        psimiConverter = new PsiToBiopax3Converter();
189                        psimiConverter.convertTab(is, os, forcePsiInteractionToComplex);
190                        os.close();
191                        break;
192                }
193
194        } catch (Exception e) {
195                throw new RuntimeException("Failed to convert " +
196                                input + "to BioPAX L3", e);
197        }
198    }
199    
200    private enum Type {
201        BIOPAX,
202        PSIMI,
203        PSIMITAB
204    }
205    
206    //read a few lines to detect it's a BioPAX vs. PSI-MI vs. PSI-MITAB data.
207        private static Type detect(String input) {              
208                StringBuilder sb = new StringBuilder();
209                try {
210                        BufferedReader reader = new BufferedReader(new FileReader(input));
211                        int linesToCheck = 20;
212                        while (linesToCheck-- > 0) {
213                                sb.append(reader.readLine()).append('\n');
214                        }
215                        reader.close();
216                } catch (IOException e) {
217                        throw new RuntimeException(e);
218                }
219                
220                String buf = sb.toString();
221                if (buf.contains("<rdf:RDF") && buf.contains("http://www.biopax.org/release/biopax")) {
222                        return Type.BIOPAX;
223                }
224                else if (buf.contains("<entrySet") && buf.contains("http://psidev.sourceforge.net/mi/rel25/")) {
225                        return Type.PSIMI;
226                }
227                else
228                        return Type.PSIMITAB; //default/guess
229        }
230
231    /*
232     *  Converts a BioPAX file to SBGN and saves it in a file.
233         *
234     */
235    public static void toSBGN(String[] argv) throws IOException
236    {
237        String input = argv[1];
238        String output = argv[2];
239
240        Model model = io.convertFromOWL(getInputStream(input));
241        L3ToSBGNPDConverter l3ToSBGNPDConverter = new L3ToSBGNPDConverter();
242        l3ToSBGNPDConverter.writeSBGN(model, output);
243    }
244
245    
246    /*
247     * Checks files by the online BioPAX validator using the built-in BioPAX validator client.
248     * 
249     * See about <a href="http://www.biopax.org/validator">BioPAX Validator Webservice</a>
250     */
251    public static void validate(String[] argv) throws IOException 
252    {
253        String input = argv[1];
254        String output = argv[2];
255        // default options
256        RetFormat outf = RetFormat.HTML;
257        boolean fix = false;
258        Integer maxErrs = null;
259        Behavior level = null; //will report both errors and warnings
260        String profile = null;
261        
262        // match optional args
263                for (int i = 3; i < argv.length; i++) {
264                        if ("html".equalsIgnoreCase(argv[i])) {
265                                outf = RetFormat.HTML;
266                        } else if ("xml".equalsIgnoreCase(argv[i])) {
267                                outf = RetFormat.XML;
268                        } else if ("biopax".equalsIgnoreCase(argv[i])) {
269                                outf = RetFormat.OWL;
270                        } else if ("auto-fix".equalsIgnoreCase(argv[i])) {
271                                fix = true;
272                        } else if ("only-errors".equalsIgnoreCase(argv[i])) {
273                                level = Behavior.ERROR;
274                        } else if ((argv[i]).toLowerCase().startsWith("maxerrors=")) {
275                                String num = argv[i].substring(10);
276                                maxErrs = Integer.valueOf(num);
277                        } else if ("notstrict".equalsIgnoreCase(argv[i])) {
278                                profile = "notstrict";
279                        }
280                }
281
282        Collection<File> files = new HashSet<File>();
283        File fileOrDir = new File(input);
284        if (!fileOrDir.canRead()) {
285            System.out.println("Cannot read " + input);
286        }
287
288        // collect files
289        if (fileOrDir.isDirectory()) {
290            // validate all the OWL files in the folder
291            FilenameFilter filter = new FilenameFilter() {
292                public boolean accept(File dir, String name) {
293                    return (name.endsWith(".owl"));
294                }
295            };
296            for (String s : fileOrDir.list(filter)) {
297                files.add(new File(fileOrDir.getCanonicalPath()
298                        + File.separator + s));
299            }
300        } else {
301            files.add(fileOrDir);
302        }
303
304        // upload and validate using the default URL:
305        // http://www.biopax.org/biopax-validator/check.html
306        OutputStream os = new FileOutputStream(output);
307        try {
308            if (!files.isEmpty()) {
309                BiopaxValidatorClient val = new BiopaxValidatorClient();
310                val.validate(fix, profile, outf, level, maxErrs, null, files.toArray(new File[]{}), os);
311            }
312        } catch (Exception ex) {
313            // fall-back: not using the remote validator; trying to read files
314            String msg = "Unable to check with the biopax-validator web service: \n " +
315                        ex.toString() + 
316                        "\n Fall-back: trying to parse the file(s) with paxtools " +
317                        "(up to the first syntax error in each file)...\n";
318            log.error(msg, ex);
319            os.write(msg.getBytes());
320
321            for (File f : files) {
322                try {
323                    Model m = io.convertFromOWL(getInputStream(f.getPath()));
324                    msg = "Model that contains "
325                            + m.getObjects().size()
326                            + " elements is successfully created from " 
327                            + f.getPath() 
328                            + " (check the console output for warnings).\n";
329                    os.write(msg.getBytes());
330                } catch (Exception e) {
331                    msg = "Error: " + e + 
332                                " in building a BioPAX Model from: " +
333                                f.getPath() + "\n";
334                    os.write(msg.getBytes());
335                    e.printStackTrace();
336                    log.error(msg);
337                }
338                os.flush();
339            }
340        }
341    }
342
343    public static void toSifnx(String[] argv) throws IOException {
344        CommonIDFetcher idFetcher = new CommonIDFetcher();
345                idFetcher.setUseUniprotIDs(argv.length > 3 && argv[3].equals("uniprot"));
346                SIFSearcher searcher = new SIFSearcher(idFetcher, SIFEnum.values());
347                File blacklistFile = new File("blacklist.txt");
348                if(blacklistFile.exists()) {
349                        log.info("toSifnx: will use the blacklist.txt (found in the current directory)");
350                        searcher.setBlacklist(new Blacklist(new FileInputStream(blacklistFile)));
351                } else {
352                        log.info("toSifnx: not blacklisting ubiquitous molecules (no blacklist.txt found)");
353                }
354        Model model = getModel(io, argv[1]);
355        ModelUtils.mergeEquivalentInteractions(model);
356                Set<SIFInteraction> binaryInts = searcher.searchSIF(model);
357                OldFormatWriter.write(binaryInts, new FileOutputStream(argv[2]));
358    }
359
360    public static void toSif(String[] argv) throws IOException {
361                CommonIDFetcher idFetcher = new CommonIDFetcher();
362
363                List<String> otherParam = new ArrayList<String>();
364                otherParam.addAll(Arrays.asList(argv).subList(3, argv.length));
365
366                idFetcher.setUseUniprotIDs(otherParam.contains("uniprot"));
367                SIFSearcher searcher = new SIFSearcher(idFetcher, SIFEnum.values());
368                File blacklistFile = new File("blacklist.txt");
369                if(blacklistFile.exists()) {
370                        log.info("toSif: will use the blacklist.txt (found in the current directory)");
371                        searcher.setBlacklist(new Blacklist(new FileInputStream(blacklistFile)));
372                } else {
373                        log.info("toSif: not blacklisting ubiquitous molecules (no blacklist.txt found)");
374                }
375
376                // check for custom fields
377                List<String> fieldList = new ArrayList<String>();
378                for (String param : otherParam)
379                {
380                        OutputColumn.Type type = OutputColumn.Type.getType(param);
381                        if ((type != null && type != OutputColumn.Type.CUSTOM) ||
382                                param.contains("/"))
383                        {
384                                fieldList.add(param);
385                        }
386                }
387
388                Model model = getModel(io, argv[1]);
389                ModelUtils.mergeEquivalentInteractions(model);
390
391                if (fieldList.isEmpty())
392                {
393                        searcher.searchSIF(model, new FileOutputStream(argv[2]), false);
394                }
395                else if (fieldList.size() == 1 &&
396                        fieldList.contains(OutputColumn.Type.MEDIATOR.name().toLowerCase()))
397                {
398                        searcher.searchSIF(model, new FileOutputStream(argv[2]), true);
399                }
400                else
401                {
402                        searcher.searchSIF(model, new FileOutputStream(argv[2]),
403                                new CustomFormat(fieldList.toArray(new String[fieldList.size()])));
404                }
405    }
406
407    public static void integrate(String[] argv) throws IOException {
408
409        Model model1 = getModel(io, argv[1]);
410        Model model2 = getModel(io, argv[2]);
411
412        Integrator integrator =
413                new Integrator(SimpleEditorMap.get(model1.getLevel()), model1, model2);
414        integrator.integrate();
415
416        io.setFactory(model1.getLevel().getDefaultFactory());
417        io.convertToOWL(model1, new FileOutputStream(argv[3]));
418    }
419
420    public static void merge(String[] argv) throws IOException {
421
422        Model model1 = getModel(io, argv[1]);
423        Model model2 = getModel(io, argv[2]);
424
425        Merger merger = new Merger(SimpleEditorMap.get(model1.getLevel()));
426        merger.merge(model1, model2);
427
428        io.setFactory(model1.getLevel().getDefaultFactory());
429        io.convertToOWL(model1, new FileOutputStream(argv[3]));
430    }
431
432        /*
433     * Generates a blacklist file
434     * (to optionally use it to exclude ubiquitous small molecules, 
435     * like ATP, when performing graph queries and exporting to
436     * SIF formats).
437     */
438    public static void blacklist(String[] argv) throws IOException {
439        Model model = getModel(io, argv[1]);
440                BlacklistGenerator gen = new BlacklistGenerator();
441                Blacklist blacklist = gen.generateBlacklist(model);
442                blacklist.write(new FileOutputStream(argv[2]));
443    }
444   
445    public static void help() {
446
447        System.out.println("(Paxtools Console) Available Operations:\n");
448        for (Command cmd : Command.values()) {
449            System.out.println(cmd.name() + " " + cmd.description);
450        }
451        System.out.println("Commands can also use compressed input files (only '.gz').\n");
452    }
453
454        public static void pattern(String[] argv) {
455                Dialog.main(argv);
456        }
457
458    private static Model getModel(BioPAXIOHandler io, String fName) throws IOException {
459        return io.convertFromOWL(getInputStream(fName));
460    }
461
462        //----- Section: Printing summary -------------------------------------------------------------|
463        
464        public static void summarize(String[] argv) throws IOException {
465
466                log.debug("Importing the input model from " + argv[1] + "...");
467                Model model = getModel(io, argv[1]);
468                log.debug("Analyzing...");
469                summarize(model, argv.length > 2 ? new PrintStream(argv[2]) : null);
470        }
471                
472        public static void summarize(Model model, PrintStream out) throws IOException {
473        // Produce a simplified version of the summary
474
475                if (out == null) out = System.out;
476
477        HashMap<String, Integer> hm = new HashMap<String, Integer>();
478
479                final SimpleEditorMap em = (model.getLevel() == BioPAXLevel.L3) 
480                                ? SimpleEditorMap.L3 : SimpleEditorMap.L2;
481
482                for (Class<? extends BioPAXElement> clazz : sortToName(em.getKnownSubClassesOf(BioPAXElement.class)))
483                {
484                        Set<? extends BioPAXElement> set = model.getObjects(clazz);
485                        int initialSize = set.size();
486                        set = filterToExactClass(set, clazz);
487                        
488                        String s = clazz.getSimpleName() + " = " + set.size();
489
490                        if (initialSize != set.size()) 
491                                s += " (and " + (initialSize - set.size()) + " children)";
492                        
493                        out.println(s);
494
495                        Set<PropertyEditor> editors = em.getEditorsOf(clazz);
496                        for (PropertyEditor editor : editors)
497                        {
498                                Method getMethod = editor.getGetMethod();
499                                Class<?> returnType = getMethod.getReturnType();
500
501                                Map<Object, Integer> cnt = new HashMap<Object, Integer>();
502
503                                if (returnType.isEnum() ||
504                                        implementsInterface(returnType, ControlledVocabulary.class))
505                                {
506                                        for (BioPAXElement ele : set)
507                                        {
508                                                Set<?> values = editor.getValueFromBean(ele);
509                                                if (values.isEmpty())
510                                                {
511                                                        increaseCnt(cnt, NULL);
512                                                }
513                                                else
514                                                {
515                                                        increaseCnt(cnt, values.iterator().next());
516                                                }
517                                        }
518                                }
519                                else if (returnType.equals(Set.class) &&
520                                        implementsInterface(editor.getRange(), ControlledVocabulary.class))
521                                {
522                                        for (BioPAXElement ele : set)
523                                        {
524                                                Set<?> values = editor.getValueFromBean(ele);
525                                                if (values.isEmpty())
526                                                {
527                                                        increaseCnt(cnt, EMPTY);
528                                                }
529                                                for (Object val : values)
530                                                {
531                                                        increaseCnt(cnt, val);
532                                                }
533                                        }
534                                }
535
536                                if (!cnt.isEmpty())
537                                {
538                                        String name = "-" 
539                                                + (returnType.equals(Set.class) ? editor.getRange().getSimpleName() : returnType.getSimpleName());
540
541                                        out.print("\t" + name + ":");
542                                        for (Object key : getOrdering(cnt))
543                                        {
544                                                out.print("\t" + key + " = " + cnt.get(key));
545                                        }
546                                        out.println();
547                                }
548                        }
549                }
550
551                String[] props = (model.getLevel() == BioPAXLevel.L3) 
552                        ? new String[]{"UnificationXref/db","RelationshipXref/db"}
553                        : new String[]{"unificationXref/DB","relationshipXref/DB"};
554
555                out.println("\nOther property counts\n");
556
557                for (String prop : props)
558                {
559                        Map<Object, Integer> cnt = new HashMap<Object, Integer>();
560                        List<String> valList = new ArrayList<String>();
561                        PathAccessor acc = new PathAccessor(prop, model.getLevel());
562                        
563                        boolean isString = false;
564                        
565                        for (Object o : acc.getValueFromModel(model))
566                        {
567                                if (o instanceof String) isString = true;
568                                
569                                String s = o.toString();
570                                valList.add(s);
571                                if (!cnt.containsKey(s)) cnt.put(s, 1);
572                                else cnt.put(s, cnt.get(s) + 1);
573                        }
574
575                        out.println(prop + "\t(" + cnt.size() + " distinct values):");
576            hm.put(prop, cnt.size());
577
578                        // If the object is String, then all counts are 1, no need to print counts.
579                        if (isString)
580                        {
581                                Collections.sort(valList);
582                                for (String s : valList)
583                                {
584                                        out.print("\t" + s);
585                                }
586                        }
587                        else
588                        {
589                                for (Object key : getOrdering(cnt))
590                                {
591                                        out.print("\t" + key + " = " + cnt.get(key));
592                                }
593                        }
594                        out.println();
595                }
596
597        }
598
599        private static List<Class<? extends BioPAXElement>> sortToName(Set<? extends Class<? extends BioPAXElement>>
600                        classes)
601        {
602                List<Class<? extends BioPAXElement>> list = new ArrayList<Class<? extends BioPAXElement>>(classes);
603
604                Collections.sort(
605                                list, new Comparator<Class<? extends  BioPAXElement>>()
606                {
607                        public int compare(Class<? extends BioPAXElement> clazz1, Class<? extends BioPAXElement> clazz2)
608                        {
609                                return clazz1.getName().substring(clazz1.getName().lastIndexOf(".")+1).compareTo(
610                                        clazz2.getName().substring(clazz2.getName().lastIndexOf(".")+1));
611                        }
612                });
613                return list;
614        }
615
616        private static List<Object> getOrdering(final Map<Object, Integer> map)
617        {
618                List<Object> list = new ArrayList<Object>(map.keySet());
619                Collections.sort(list, new Comparator<Object>()
620                {
621                        public int compare(Object key1, Object key2)
622                        {
623                                int cnt1 = map.get(key1);
624                                int cnt2 = map.get(key2);
625
626                                if (cnt1 == cnt2) return key1.toString().compareTo(key2.toString());
627                                else return cnt2 - cnt1;
628                        }
629                });
630                return list;
631        }
632        
633        private static Set<BioPAXElement> filterToExactClass(Set<? extends BioPAXElement> classSet, Class<?> clazz)
634        {
635                Set<BioPAXElement> exact = new HashSet<BioPAXElement>();
636                for (BioPAXElement ele : classSet)
637                {
638                        if (ele.getModelInterface().equals(clazz)) exact.add(ele);
639                }
640                return exact;
641        }
642
643        private static final Object NULL = new Object(){
644                @Override
645                public String toString()
646                {
647                        return "NULL";
648                }
649        };
650
651        private static final Object EMPTY = new Object(){
652                @Override
653                public String toString()
654                {
655                        return "EMPTY";
656                }
657        };
658
659        private static boolean implementsInterface(Class clazz, Class inter)
660        {
661                for (Class anInter : clazz.getInterfaces())
662                {
663                        if (anInter.equals(inter)) return true;
664                }
665                return false;
666        }
667
668        private static void increaseCnt(Map<Object, Integer> cnt, Object key)
669        {
670                if (!cnt.containsKey(key)) cnt.put(key, 0);
671                cnt.put(key, cnt.get(key) + 1);
672        }
673        
674        
675        // gets new IS - either FIS or GzipIS if .gz extension present
676        private static InputStream getInputStream(String path) throws IOException {
677                InputStream is = new FileInputStream(path);
678                return (path.endsWith(".gz")) ? new GZIPInputStream(is) : is ;
679        }
680
681        //-- End of Section; Printing summary ---------------------------------------------------------|
682        
683    enum Command {
684        merge("<file1> <file2> <output>\n" +
685                        "\t- merges file2 into file1 and writes it into output")
686                        {public void run(String[] argv) throws IOException{merge(argv);} },
687        toSif("<input> <output> [hgnc|uniprot]\n" +
688                        "\t- converts model to the simple interaction format; will use blacklist.txt file in the current directory, if present")
689                        {public void run(String[] argv) throws IOException{toSif(argv);} },
690        toSifnx("<input> <output> [hgnc|uniprot] [mediator] [pubmed] [pathway] [resource] [source_loc] [target_loc] [path/to/a/mediator/field]\n" +
691                        "\t- converts model to the extended simple interaction format; will use blacklist.txt file in the current directory, if present")
692                        {public void run(String[] argv) throws IOException{toSifnx(argv);} },
693        toSbgn("<biopax.owl> <output.sbgn>\n" +
694                        "\t- converts model to the SBGN format.")
695                {public void run(String[] argv) throws IOException { toSBGN(argv); } },
696        validate("<path> <out> [xml|html|biopax] [auto-fix] [only-errors] [maxerrors=n] [notstrict]\n" +
697                        "\t- validate BioPAX file/directory (up to ~25MB in total size, -\n" +
698                        "\totherwise download and run the stand-alone validator)\n" +
699                        "\tin the directory using the online validator service\n" +
700                        "\t(generates html or xml report, or gets the processed biopax\n" +
701                        "\t(cannot be perfect though) see http://www.biopax.org/validator)")
702                        {public void run(String[] argv) throws IOException{validate(argv);} },
703        integrate("<file1> <file2> <output>\n" +
704                        "\t- integrates file2 into file1 and writes it into output (experimental)")
705                        {public void run(String[] argv) throws IOException{integrate(argv);} },
706        toLevel3("<input> <output>\n" +
707                        "\t- converts BioPAX level 1 or 2, PSI-MI 2.5 and PSI-MITAB to the level 3 file;\n" +
708                        "\tuse -Dpaxtools.converter.psi.interaction=complex java option \n" +
709                        "\tto force PSI Interaction to BioPAX Complex convertion instead of \n" +
710                        "\tto MolecularInteraction (default).")
711                        {public void run(String[] argv) throws IOException{toLevel3(argv);} },
712        toGSEA("<input> <output> <database> [crossSpeciesCheck] [skipSubPathways]\n" +
713                        "\t- converts Level 1 or 2 or 3 to GSEA output.\n"
714                + "\tUses that database identifier or the biopax URI if database is \"NONE\".\n"
715                + "\t[crossSpeciesCheck] - optional cross-species check ensures participant protein is from same species\n"
716                + "\tas pathway (values: true/false; if false, organism there will be always 'unspecified').\n"
717                                + "\t[skipSubPathways] - optional, true (always), false (never), or a semicolon-separated list of\n"
718                                + "\tProvenance_uri1;Provenance_uri2;.. for which the converter won't traverse\n"
719                                + "\tinto sub-pathways of each pathway in order to collect all the proteins (useful e.g., with KEGG data).")
720                        {public void run(String[] argv) throws IOException{toGSEA(argv);} },
721        fetch("<input> <Uri1,Uri2,..> <output>\n" +
722                        "\t- extracts a self-integral BioPAX sub-model from file1 and writes to the output.")
723                        {public void run(String[] argv) throws IOException{fetch(argv);} },
724        getNeighbors("<input> <id1,id2,..> <output>\n" +
725                        "\t- nearest neighborhood graph query (id1,id2 - of Entity sub-class only)")
726                        {public void run(String[] argv) throws IOException{getNeighbors(argv);} },
727        summarize("<input> [<output>]\n" +
728                        "\t- prints a summary of the contents of the model to the output file (if not provided - to stdout)")
729                        {public void run(String[] argv) throws IOException{summarize(argv);} },
730                blacklist("<input> <output>\n" +
731                        "\t- creates a blacklist of ubiquitous small molecules, like ATP, \n"
732                        + "\tfrom the BioPAX model and writes it to the output file. The blacklist can be used with\n "
733                        + "\tpaxtools graph queries or when converting from the SAME BioPAX data to the SIF formats.")
734                                {public void run(String[] argv) throws IOException{blacklist(argv);} },
735                pattern("\n\t- BioPAX pattern search tool (opens a new dialog window)")
736                                {public void run(String[] argv) throws IOException{pattern(argv);} },
737        help("\n\t- prints this screen and exits\n")
738                        {public void run(String[] argv) throws IOException{help();} };
739
740        String description;
741        int params;
742
743        Command(String description) {
744            this.description = description;
745        }
746
747        public abstract void run(String[] argv) throws IOException;
748    }
749}