001/*
002 *                    BioJava development code
003 *
004 * This code may be freely distributed and modified under the
005 * terms of the GNU Lesser General Public Licence.  This should
006 * be distributed with the code.  If you do not have a copy,
007 * see:
008 *
009 *      http://www.gnu.org/copyleft/lesser.html
010 *
011 * Copyright for this code is held jointly by the individual
012 * authors.  These should be listed in @author doc comments.
013 *
014 * For more information on the BioJava project and its aims,
015 * or to join the biojava-l mailing list, visit the home page
016 * at:
017 *
018 *      http://www.biojava.org/
019 *
020 * Created on Nov 2, 2009
021 * Author: Andreas Prlic
022 *
023 */
024
025package org.biojava.nbio.structure.align.ce;
026
027
028import org.biojava.nbio.structure.Atom;
029import org.biojava.nbio.structure.Structure;
030import org.biojava.nbio.structure.StructureException;
031import org.biojava.nbio.structure.StructureTools;
032import org.biojava.nbio.structure.align.MultiThreadedDBSearch;
033import org.biojava.nbio.structure.align.StructureAlignment;
034import org.biojava.nbio.structure.align.model.AFPChain;
035import org.biojava.nbio.structure.align.util.*;
036import org.biojava.nbio.structure.align.xml.AFPChainXMLConverter;
037import org.biojava.nbio.structure.io.LocalPDBDirectory.FetchBehavior;
038import org.biojava.nbio.structure.io.PDBFileReader;
039
040import java.beans.Introspector;
041import java.io.*;
042import java.lang.reflect.InvocationTargetException;
043import java.net.URL;
044import java.util.ArrayList;
045import java.util.Iterator;
046import java.util.List;
047
048
049/**
050 * Base class for a new structure alignment CLI.
051 *
052 * <p>To add a new StructureAlignment with a CLI similar to CE or FATCAT,
053 * <ol>
054 * <li>Implement StructureAlignment with the main algorithm
055 * <li>Implement ConfigStrucAligParams. This provides the parameters for the GUI.
056 * <li>Subclass StartupParameters (can be an inner class) with the same parameters
057 *     described in the ConfigStrucAligParams.
058 * <li>Subclass AbstractUserArgumentProcessor, with the getStartupParams() method
059 *     returning a fresh instance of the custom StartupParameters
060 * <li>Implement the getParameters() method to copy values from the StartupParameters
061 *     to the ConfigStrucAligParams.
062 * </ol>
063 *
064 * <p>Note that reflection is used in a number of places, so the CLI argument names
065 * must match the get/set functions in both parameter beans.
066 * <ul>
067 * <li>AlignmentGUI automatically takes parameter names and types from the
068 *     ConfigStrucAligParams
069 * <li>AbstractUserArgumentProcessor also takes parameter names and help descriptions
070 *     from ConfigStrucAligParams, but it saves arguments to the StartupParameter
071 *     bean.
072 * </ul>
073 * This means that both beans should be kept in sync.
074 *
075 * @author Andreas
076 * @author Spencer
077 *
078 */
079public abstract class AbstractUserArgumentProcessor implements UserArgumentProcessor {
080
081        public static String newline = System.getProperty("line.separator");
082
083        protected StartupParameters params ;
084
085        public static final List<String> mandatoryArgs= new ArrayList<String>();
086
087        protected AbstractUserArgumentProcessor(){
088                params = getStartupParametersInstance();
089        }
090
091        /**
092         * StartupParameters is a bean to store all the possible
093         * command line parameters.
094         *
095         * The `StartupParameter` class contains the basic set of CLI parameters
096         * common to all `StructureAligmnent`s. This method should return a subclass
097         * of StartupParameters which has been extended to store values for all
098         * additional parameters.
099         * @return A new instance of the correct StartupParameters subclass
100         */
101        protected abstract StartupParameters getStartupParametersInstance();
102
103        public abstract StructureAlignment getAlgorithm();
104        public abstract Object getParameters();
105        public abstract String getDbSearchLegend();
106
107        @Override
108        public void process(String[] argv){
109
110                printAboutMe();
111
112//              if(argv.length == 0 ) {
113//                      System.out.println(printHelp());
114//                      return;
115//              }
116
117                for (int i = 0 ; i < argv.length; i++){
118                        String arg   = argv[i];
119
120                        // help string
121                        if(arg.equalsIgnoreCase("-h") || arg.equalsIgnoreCase("-help")
122                                        || arg.equalsIgnoreCase("--help") )
123                        {
124                                System.out.println(printHelp());
125                                return;
126                        }
127                        // version
128                        if(arg.equalsIgnoreCase("-version") || arg.equalsIgnoreCase("--version")) {
129                                StructureAlignment alg = getAlgorithm();
130                                System.out.println(alg.getAlgorithmName() + " v." + alg.getVersion() );
131                                return;
132                        }
133
134                        String value = null;
135                        if ( i < argv.length -1)
136                                value = argv[i+1];
137
138                        // if value starts with - then the arg does not have a value.
139                        if (value != null && value.startsWith("-"))
140                                value = null;
141                        else
142                                i++;
143
144
145                        String[] tmp = {arg,value};
146
147                        //System.out.println(arg + " " + value);
148
149                        try {
150
151                                CliTools.configureBean(params, tmp);
152
153                        } catch (ConfigurationException e){
154                                System.err.println("Error: "+e.getLocalizedMessage());
155                                System.exit(1); return;
156                        }
157                }
158
159                if ( params.getPdbFilePath() != null){
160                        System.setProperty(UserConfiguration.PDB_DIR,params.getPdbFilePath());
161                }
162
163                if ( params.getCacheFilePath() != null){
164                        System.setProperty(UserConfiguration.PDB_CACHE_DIR,params.getCacheFilePath());
165                }
166
167                if ( params.isShowMenu()){
168                        System.err.println("showing menu...");
169                        try {
170                                GuiWrapper.showAlignmentGUI();
171                        } catch (Exception e){
172                                System.err.println(e.getMessage());
173                                e.printStackTrace();
174                        }
175                }
176
177                if ( params.getShowDBresult() != null){
178                        // user wants to view DB search results:
179
180
181                        System.err.println("showing DB results...");
182                        try {
183                                GuiWrapper.showDBResults(params);
184                        } catch (Exception e){
185                                System.err.println(e.getMessage());
186                                e.printStackTrace();
187                        }
188
189                }
190
191                String pdb1  = params.getPdb1();
192                String file1 = params.getFile1();
193
194
195                try {
196                        if (pdb1 != null || file1 != null){
197                                runPairwise();
198                                return;
199                        }
200
201                        if ( params.getAlignPairs() != null){
202                                runDBSearch();
203                                return;
204                        }
205
206                        if ( params.getSearchFile() != null){
207                                runDBSearch();
208                                return;
209                        }
210                } catch (ConfigurationException e) {
211                        System.err.println(e.getLocalizedMessage());
212                        System.exit(1); return;
213                }
214
215                System.out.println(printHelp());
216                System.err.println("Error: insufficient arguments.");
217                System.exit(1); return;
218        }
219
220
221
222
223
224        public static void printAboutMe() {
225                try {
226                        ResourceManager about = ResourceManager.getResourceManager("about");
227
228                        String version = about.getString("project_version");
229                        String build   = about.getString("build");
230
231                        System.out.println("Protein Comparison Tool " + version + " " + build);
232                } catch (Exception e){
233                        e.printStackTrace();
234                }
235
236
237        }
238
239
240        private void runDBSearch() throws ConfigurationException{
241
242
243                String pdbFilePath = params.getPdbFilePath();
244
245                if ( pdbFilePath == null || pdbFilePath.equals("")){
246
247                        UserConfiguration c = new UserConfiguration();
248                        pdbFilePath = c.getPdbFilePath();
249                        System.err.println("You did not specify the -pdbFilePath parameter. Defaulting to "+pdbFilePath+".");
250                }
251
252                String cacheFilePath = params.getCacheFilePath();
253
254                if ( cacheFilePath == null || cacheFilePath.equals("")){
255                        cacheFilePath = pdbFilePath;
256
257                }
258
259
260                AtomCache cache = new AtomCache(pdbFilePath, pdbFilePath);
261
262                String alignPairs = params.getAlignPairs();
263
264                String searchFile = params.getSearchFile();
265
266                if ( alignPairs == null || alignPairs.equals("")) {
267                        if ( searchFile == null || searchFile.equals("")){
268                                throw new ConfigurationException("Please specify -alignPairs or -searchFile !");
269                        }
270                }
271
272                String outputFile = params.getOutFile();
273
274                if ( outputFile == null || outputFile.equals("")){
275                        throw new ConfigurationException("Please specify the mandatory argument -outFile!");
276                }
277
278                System.out.println("running DB search with parameters: " + params);
279
280                if ( alignPairs != null && ! alignPairs.equals("")) {
281                        runAlignPairs(cache, alignPairs, outputFile);
282                }  else {
283                        // must be a searchFile request...
284
285                        int useNrCPUs = params.getNrCPU();
286
287                        runDbSearch(cache,searchFile, outputFile, useNrCPUs, params);
288                }
289        }
290
291
292        /** Do a DB search with the input file against representative PDB domains
293         *
294         * @param cache
295         * @param searchFile
296         * @param outputFile
297         * @throws ConfigurationException
298         */
299        private void runDbSearch(AtomCache cache, String searchFile,
300                        String outputFile,int useNrCPUs, StartupParameters params) throws ConfigurationException {
301
302
303                System.out.println("will use " + useNrCPUs + " CPUs.");
304
305                PDBFileReader reader = new PDBFileReader();
306                Structure structure1 = null ;
307                try {
308                        structure1 = reader.getStructure(searchFile);
309                } catch (IOException e) {
310                        throw new ConfigurationException("could not parse as PDB file: " + searchFile);
311                }
312
313                File searchF = new File(searchFile);
314                String name1 = "CUSTOM";
315
316
317
318                StructureAlignment algorithm =  getAlgorithm();
319
320                MultiThreadedDBSearch dbSearch = new MultiThreadedDBSearch(name1,
321                                structure1,
322                                outputFile,
323                                algorithm,
324                                useNrCPUs,
325                                params.isDomainSplit());
326
327                dbSearch.setCustomFile1(searchF.getAbsolutePath());
328
329                dbSearch.run();
330
331
332        }
333
334
335        private void runAlignPairs(AtomCache cache, String alignPairs,
336                        String outputFile) {
337                try {
338                        File f = new File(alignPairs);
339
340                        BufferedReader is = new BufferedReader (new InputStreamReader(new FileInputStream(f)));
341
342                        BufferedWriter out = new BufferedWriter(new FileWriter(outputFile, true));
343
344                        StructureAlignment algorithm =  getAlgorithm();
345
346                        String header = "# algorithm:" + algorithm.getAlgorithmName();
347                        out.write(header);
348                        out.write(newline);
349
350                        out.write("#Legend: " + newline );
351                        String legend = getDbSearchLegend();
352                        out.write(legend + newline );
353                        System.out.println(legend);
354                        String line = null;
355                        while ( (line = is.readLine()) != null){
356                                if ( line.startsWith("#"))
357                                        continue;
358
359                                String[] spl = line.split(" ");
360
361                                if ( spl.length != 2) {
362                                        System.err.println("wrongly formattted line. Expected format: 4hhb.A 4hhb.B but found " + line);
363                                        continue;
364                                }
365
366                                String pdb1 = spl[0];
367                                String pdb2 = spl[1];
368
369
370                                Structure structure1 = cache.getStructure(pdb1);
371                                Structure structure2 = cache.getStructure(pdb2);
372
373                                Atom[] ca1;
374                                Atom[] ca2;
375
376
377                                ca1 = StructureTools.getRepresentativeAtomArray(structure1);
378                                ca2 = StructureTools.getRepresentativeAtomArray(structure2);
379
380                                Object jparams = getParameters();
381
382                                AFPChain afpChain;
383
384                                afpChain = algorithm.align(ca1, ca2, jparams);
385                                afpChain.setName1(pdb1);
386                                afpChain.setName2(pdb2);
387
388                                String result = getDbSearchResult(afpChain);
389                                out.write(result);
390                                System.out.print(result);
391
392                                checkWriteFile(afpChain,ca1,ca2,true);
393                        }
394
395                        out.close();
396                        is.close();
397                } catch(Exception e){
398                        e.printStackTrace();
399                }
400        }
401
402
403        private void runPairwise() throws ConfigurationException{
404
405                String name1 = params.getPdb1();
406                String file1 = params.getFile1();
407
408                if ( name1 == null && file1 == null){
409                        throw new ConfigurationException("You did not specify the -pdb1 or -file1 parameter. Can not find query PDB id for alignment.");
410                }
411
412                if ( file1 == null) {
413                        if ( name1.length() < 4) {
414                                throw new ConfigurationException("-pdb1 does not look like a PDB ID. Please specify PDB code or PDB.chainName.");
415                        }
416                }
417
418
419
420                String name2 = params.getPdb2();
421                String file2 = params.getFile2();
422                if ( name2 == null && file2 == null ){
423                        throw new ConfigurationException("You did not specify the -pdb2 or -file2 parameter. Can not find target PDB id for alignment.");
424                }
425
426                if ( file2 == null ){
427                        if ( name2.length() < 4) {
428                                throw new ConfigurationException("-pdb2 does not look like a PDB ID. Please specify PDB code or PDB.chainName.");
429                        }
430                }
431
432                // first load two example structures
433
434                Structure structure1 = null;
435                Structure structure2 = null;
436
437                String path = params.getPdbFilePath();
438
439                if ( file1 == null || file2 == null) {
440                        if ( path == null){
441                                UserConfiguration c = new UserConfiguration();
442                                path = c.getPdbFilePath();
443                                System.err.println("You did not specify the -pdbFilePath parameter. Defaulting to "+path+".");
444                        }
445
446                        AtomCache cache = new AtomCache(path, path);
447                        if(params.isAutoFetch()) {
448                                cache.setFetchBehavior(FetchBehavior.DEFAULT);
449                        } else {
450                                cache.setFetchBehavior(FetchBehavior.LOCAL_ONLY);
451                        }
452                        structure1 = getStructure(cache, name1, file1);
453                        structure2 = getStructure(cache, name2, file2);
454                } else {
455
456                        structure1 = getStructure(null, name1, file1);
457                        structure2 = getStructure(null, name2, file2);
458                }
459
460
461
462                if ( structure1 == null){
463                        System.err.println("structure 1 is null, can't run alignment.");
464                        System.exit(1); return;
465                }
466
467                if ( structure2 == null){
468                        System.err.println("structure 2 is null, can't run alignment.");
469                        System.exit(1); return;
470                }
471
472                if ( name1 == null) {
473                        name1 = structure1.getName();
474                }
475                if ( name2 == null) {
476                        name2 = structure2.getName();
477                }
478
479                //                   default:      new:
480                // 1buz - 1ali : time: 8.3s eqr 68 rmsd 3.1 score 161 | time 6.4 eqr 58 rmsd 3.0 scre 168
481                // 5pti - 1tap : time: 6.2s eqr 48 rmsd 2.67 score 164 | time 5.2 eqr 49 rmsd 2.9 score 151
482                // 1cdg - 8tim
483                // 1jbe - 1ord
484                // 1nbw.A - 1kid
485                // 1t4y - 1rp5
486
487
488                try {
489
490                        Atom[] ca1;
491                        Atom[] ca2;
492
493                        ca1 = StructureTools.getRepresentativeAtomArray(structure1);
494                        ca2 = StructureTools.getRepresentativeAtomArray(structure2);
495
496                        StructureAlignment algorithm =  getAlgorithm();
497                        Object jparams = getParameters();
498
499                        AFPChain afpChain;
500
501                        afpChain = algorithm.align(ca1, ca2, jparams);
502                        afpChain.setName1(name1);
503                        afpChain.setName2(name2);
504
505                        if ( params.isShow3d()){
506
507                                if (! GuiWrapper.isGuiModuleInstalled()) {
508                                        System.err.println("The biojava-structure-gui module is not installed. Please install!");
509                                } else {
510
511                                        try {
512
513                                                Object jmol = GuiWrapper.display(afpChain,ca1,ca2);
514
515                                                GuiWrapper.showAlignmentImage(afpChain, ca1,ca2,jmol);
516
517                                        } catch (Exception e){
518
519                                                System.err.println(e.getMessage());
520                                                e.printStackTrace();
521                                        }
522                                        //StructureAlignmentJmol jmol = algorithm.display(afpChain,ca1,ca2,hetatms1, nucs1, hetatms2, nucs2);
523
524                                        //String result = afpChain.toFatcat(ca1, ca2);
525                                        //String rot = afpChain.toRotMat();
526
527                                        //DisplayAFP.showAlignmentImage(afpChain, ca1,ca2,jmol);
528                                }
529                        }
530
531
532                        checkWriteFile(afpChain,ca1, ca2, false);
533
534
535
536
537                        if ( params.isPrintXML()){
538                                String fatcatXML = AFPChainXMLConverter.toXML(afpChain,ca1,ca2);
539                                System.out.println(fatcatXML);
540                        }
541                        if ( params.isPrintFatCat()) {
542                                // default output is to XML on sysout...
543                                System.out.println(afpChain.toFatcat(ca1, ca2));
544                        }
545                        if ( params. isPrintCE()){
546                                System.out.println(afpChain.toCE(ca1, ca2));
547                        }
548
549                } catch (IOException e) {
550                        e.printStackTrace();
551                        System.exit(1); return;
552                } catch (ClassNotFoundException e) {
553                        e.printStackTrace();
554                        System.exit(1); return;
555                } catch (NoSuchMethodException e) {
556                        e.printStackTrace();
557                        System.exit(1); return;
558                } catch (InvocationTargetException e) {
559                        e.printStackTrace();
560                        System.exit(1); return;
561                } catch (IllegalAccessException e) {
562                        e.printStackTrace();
563                        System.exit(1); return;
564                } catch (StructureException e) {
565                        e.printStackTrace();
566                        System.exit(1); return;
567                }
568        }
569
570        /** check if the result should be written to the local file system
571         *
572         * @param params2
573         * @param afpChain
574         * @param ca1
575         * @param ca2
576         * @throws IOException If an error occurs when writing the afpChain to XML
577         * @throws ClassNotFoundException If an error occurs when invoking jmol
578         * @throws NoSuchMethodException If an error occurs when invoking jmol
579         * @throws InvocationTargetException If an error occurs when invoking jmol
580         * @throws IllegalAccessException If an error occurs when invoking jmol
581         * @throws StructureException
582         */
583        private void checkWriteFile( AFPChain afpChain, Atom[] ca1, Atom[] ca2, boolean dbsearch) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, StructureException
584                        {
585                String output = null;
586                if ( params.isOutputPDB()){
587                        if (! GuiWrapper.isGuiModuleInstalled()) {
588                                System.err.println("The biojava-structure-gui module is not installed. Please install!");
589                                output = AFPChainXMLConverter.toXML(afpChain,ca1,ca2);
590                        } else {
591
592                                Structure tmp = AFPAlignmentDisplay.createArtificalStructure(afpChain, ca1, ca2);
593                                output = "TITLE  " + afpChain.getAlgorithmName() + " " + afpChain.getVersion()  + " ";
594                                output += afpChain.getName1() + " vs. " + afpChain.getName2();
595                                output += newline;
596                                output += tmp.toPDB();
597                        }
598                } else  if ( params.getOutFile() != null) {
599                        // output by default is XML
600                        // write the XML to a file...
601                        output = AFPChainXMLConverter.toXML(afpChain,ca1,ca2);
602
603                } else if ( params.getSaveOutputDir() != null){
604                        output = AFPChainXMLConverter.toXML(afpChain,ca1,ca2);
605                }
606
607                // no output requested.
608                if ( output == null)
609                        return;
610
611                String fileName = null;
612
613                if ( dbsearch ){
614                        if ( params.getSaveOutputDir() != null) {
615
616                                // we currently don't have a naming convention for how to store results for custom files
617                                // they will be re-created on the fly
618                                if ( afpChain.getName1().startsWith("file:") || afpChain.getName2().startsWith("file:"))
619                                        return;
620                                fileName = params.getSaveOutputDir();
621                                fileName += getAutoFileName(afpChain);
622
623                        } else {
624                                return;
625                        }
626
627                        //
628                        //else {
629                        //      fileName = getAutoFileName(afpChain);
630                        //}
631                } else
632
633                        if ( params.getOutFile() != null) {
634                                fileName = params.getOutFile();
635                        }
636
637                if (fileName == null) {
638                        System.err.println("Can't write outputfile. Either provide a filename using -outFile or set -autoOutputFile to true .");
639                        System.exit(1); return;
640                }
641                //System.out.println("writing results to " + fileName + " " + params.getSaveOutputDir());
642
643                FileOutputStream out; // declare a file output object
644                PrintStream p; // declare a print stream object
645
646                        // Create a new file output stream
647                        out = new FileOutputStream(fileName);
648
649                        // Connect print stream to the output stream
650                        p = new PrintStream( out );
651
652                        p.println (output);
653
654                        p.close();
655
656
657
658        }
659
660
661        private String getAutoFileName(AFPChain afpChain){
662                String fileName =afpChain.getName1()+"_" + afpChain.getName2()+"_"+afpChain.getAlgorithmName();
663
664                if (params.isOutputPDB() )
665                        fileName += ".pdb";
666                else
667                        fileName += ".xml";
668                return fileName;
669        }
670
671
672        private Structure getStructure(AtomCache cache, String name1, String file)
673        {
674
675                PDBFileReader reader = new PDBFileReader();
676                if ( file != null ){
677                        try {
678                                // check if it is a URL:
679                                try {
680                                        URL url = new URL(file);
681                                        System.out.println(url);
682
683                                        Structure s = reader.getStructure(url);
684
685                                        return fixStructureName(s,file);
686
687                                } catch ( Exception e){
688                                        System.err.println(e.getMessage());
689                                }
690                                File f= new File(file);
691                                System.out.println("file from local " + f.getAbsolutePath());
692                                Structure s= reader.getStructure(f);
693                                return fixStructureName(s, file);
694                        } catch (Exception e){
695                                System.err.println("general exception:" + e.getMessage());
696                                System.err.println("unable to load structure from " + file);
697                                return null;
698                        }
699                }
700                try {
701                        Structure s = cache.getStructure(name1);
702                        return s;
703                } catch ( Exception e){
704                        System.err.println(e.getMessage());
705                        System.err.println("unable to load structure from dir: " + cache.getPath() + "/"+ name1);
706                        return null;
707                }
708
709        }
710
711        /** apply a number of rules to fix the name of the structure if it did not get set during loading.
712         *
713         * @param s
714         * @param file
715         * @return
716         */
717        private Structure fixStructureName(Structure s, String file) {
718
719                if ( s.getName() != null && (! s.getName().equals("")))
720                        return s;
721
722                s.setName(s.getPDBCode());
723
724                if ( s.getName() == null || s.getName().equals("")){
725                        File f = new File(file);
726                        s.setName(f.getName());
727                }
728                return s;
729        }
730
731        public String getDbSearchResult(AFPChain afpChain){
732                return afpChain.toDBSearchResult();
733        }
734
735        @Override
736        public String printHelp() {
737                StringBuffer buf = new StringBuffer();
738                StructureAlignment alg = getAlgorithm();
739
740                buf.append("-------------------").append(newline);
741                buf.append(alg.getAlgorithmName() + " v." + alg.getVersion() + " help: " + newline);
742                buf.append("-------------------").append(newline);
743                buf.append(newline);
744
745                buf.append(alg.getAlgorithmName()).append(" accepts the following parameters:").append(newline);
746                buf.append(newline);
747
748                buf.append("--- pairwise alignments ---").append(newline);
749                buf.append(" two files to align can be specified by providing a path to a file, or a URL:").append(newline);
750                buf.append("   -file1 the first file to align").append(newline);
751                buf.append("   -file2 the second file to align").append(newline);
752                buf.append(" alternatively you can specify PDB files by their PDB ids:").append(newline);
753                buf.append("   -pdbFilePath  Path to the directory in your file system that contains the PDB files.").append(newline);
754                buf.append("   -pdb1  PDB ID of target structure. Chain IDs are optional. In order to specify chain IDs write e.g: 5pti.A").append(newline);
755                buf.append("   -pdb2  PDB ID of query structure. Chain IDs are optional. In order to specify chain IDs write e.g: 5pti.A").append(newline);
756                buf.append(newline);
757
758                buf.append("   -h / -help / --help : print this help string.").append(newline);
759                buf.append("   -version: print version info").append(newline);
760                buf.append("   -printXML true/false print the XML representation of the alignment on stdout.").append(newline);
761                buf.append("   -printFatCat true/false print the original FATCAT output to stdout.").append(newline);
762                buf.append("   -printCE true/false print the result in CE style").append(newline);
763                buf.append("   -show3d print a 3D visualisation of the alignment (requires jmolapplet.jar in classpath)").append(newline);
764                buf.append("   -outFile file to write the output to (default: writes XML representation).").append(newline);
765                buf.append("   -outputPDB use this flag together with -outFile to dump the PDB file of the aligned structures, instead of the XML representation, instead of XML").append(newline);
766                buf.append("   -autoFetch true/false if set to true PDB files will automatically get downloaded and stored in the right location. (default: false)").append(newline);
767                buf.append("   -showMenu displays the menu that allows to run alignments through a user interface.").append(newline);
768                buf.append(newline);
769
770                buf.append("--- custom searches ---").append(newline);
771                buf.append("   -alignPairs (mandatory) path to a file that contains a set of pairs to compair").append(newline);
772                buf.append("   -outFile (mandatory) a file that will contain the summary of all the pairwise alignments").append(newline);
773                buf.append(newline);
774
775                buf.append("--- database searches ---").append(newline);
776                buf.append("   -searchFile (mandatory) path to a PDB file that should be used in the search").append(newline);
777                buf.append("   -outFile (mandatory) a directory that will contain the results of the DB search").append(newline);
778                buf.append("   -nrCPU (optional) Number of CPUs to use for the database search. By default will use the all, but one CPU in the system.").append(newline);
779                buf.append("   -pdbFilePath (mandatory) Path to the directory in your file system that contains the PDB files.").append(newline);
780                buf.append("   -saveOutputDir (optional) a directory that will contain the detailed outputs of the alignments. By default will write XML files, if used together with -outputPDB, will write PDB files of the alignment.").append(newline);
781                buf.append(newline);
782
783                buf.append(" Once DB seaches are complete it is possible to view the results with:").append(newline);
784                buf.append("   -showDBresult (optional) path to a DB outFile to show. Also provide the -pdbFilePath parameter to enable visualisation of results.").append(newline);
785                buf.append(newline);
786
787                ConfigStrucAligParams params = alg.getParameters();
788                List<String> paramNames = params.getUserConfigParameters();
789                List<String> paramHelp = params.getUserConfigHelp();
790
791                assert(paramNames.size() == paramHelp.size());
792
793                int size = Math.min(paramNames.size(), paramHelp.size());
794                if(size > 0) {
795                        Iterator<String> namesIt = paramNames.iterator();
796                        Iterator<String> helpIt = paramHelp.iterator();
797
798                        buf.append("--- ").append(alg.getAlgorithmName()).append(" parameters: ---").append(newline);
799                        for(int i = 0; i< size; i++) {
800                                String name = namesIt.next();
801                                buf.append("   -").append(Introspector.decapitalize(name));
802                                buf.append(" ").append(helpIt.next());
803                                buf.append(newline);
804                        }
805                }
806                buf.append(newline);
807
808                buf.append(" For boolean arguments: if neither the text >true< or >false< is provided it is assumed to mean >true<. Instead of >-argument false< it is also possible to write -noArgument.").append(newline);
809                buf.append(newline);
810
811                buf.append("--- How to specify what to align ---").append(newline);
812                buf.append(" If only a PDB code is provided, the whole structure will be used for the alignment.").append(newline);
813                buf.append(" To specify a particular chain write as: 4hhb.A (chain IDs are case sensitive, PDB ids are not)").append(newline);
814                buf.append(" To specify that the 1st chain in a structure should be used write: 4hhb:0 .").append(newline);
815                buf.append(" In order to align SCOP domains, provide pdb1/pdb2 as: d4hhba_ Note: if SCOP is not installed at the -pdbFilePath, will automatically download and install.").append(newline);
816                buf.append(newline);
817
818                return buf.toString();
819        }
820
821}