58271c33916666bf84b54afeafb97daf70fd6fd2
[jalview.git] / forester / java / src / org / forester / util / ForesterUtil.java
1 // $Id:
2 // FORESTER -- software libraries and applications
3 // for evolutionary biology research and applications.
4 //
5 // Copyright (C) 2008-2009 Christian M. Zmasek
6 // Copyright (C) 2008-2009 Burnham Institute for Medical Research
7 // All rights reserved
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 //
23 // Contact: phylosoft @ gmail . com
24 // WWW: https://sites.google.com/site/cmzmasek/home/software/forester
25
26 package org.forester.util;
27
28 import java.awt.Color;
29 import java.io.BufferedReader;
30 import java.io.BufferedWriter;
31 import java.io.File;
32 import java.io.FileInputStream;
33 import java.io.FileNotFoundException;
34 import java.io.FileOutputStream;
35 import java.io.FileReader;
36 import java.io.FileWriter;
37 import java.io.IOException;
38 import java.io.InputStream;
39 import java.io.InputStreamReader;
40 import java.io.StringReader;
41 import java.io.Writer;
42 import java.math.BigDecimal;
43 import java.net.URL;
44 import java.net.URLConnection;
45 import java.text.DateFormat;
46 import java.text.DecimalFormat;
47 import java.text.DecimalFormatSymbols;
48 import java.text.NumberFormat;
49 import java.text.ParseException;
50 import java.text.SimpleDateFormat;
51 import java.util.ArrayList;
52 import java.util.Collection;
53 import java.util.Date;
54 import java.util.List;
55 import java.util.Map;
56 import java.util.Map.Entry;
57 import java.util.Set;
58 import java.util.SortedMap;
59 import java.util.SortedSet;
60 import java.util.TreeMap;
61 import java.util.TreeSet;
62 import java.util.regex.Matcher;
63 import java.util.regex.Pattern;
64
65 import org.forester.archaeopteryx.Constants;
66 import org.forester.phylogeny.PhylogenyNode;
67 import org.forester.phylogeny.data.Distribution;
68 import org.forester.phylogeny.data.Sequence;
69 import org.forester.phylogeny.data.Taxonomy;
70 import org.forester.protein.BasicProtein;
71 import org.forester.protein.Domain;
72 import org.forester.protein.Protein;
73 import org.forester.sequence.MolecularSequence;
74 import org.forester.sequence.MolecularSequence.TYPE;
75 import org.forester.surfacing.SurfacingUtil;
76
77 public final class ForesterUtil {
78
79     public final static String       FILE_SEPARATOR                   = System.getProperty( "file.separator" );
80     public static final NumberFormat FORMATTER_06;
81     public static final NumberFormat FORMATTER_3;
82     public static final NumberFormat FORMATTER_6;
83     public static final NumberFormat FORMATTER_9;
84     public final static String       JAVA_VENDOR                      = System.getProperty( "java.vendor" );
85     public final static String       JAVA_VERSION                     = System.getProperty( "java.version" );
86     public final static String       LINE_SEPARATOR                   = System.getProperty( "line.separator" );
87     public static final String       NCBI_GI                          = "http://www.ncbi.nlm.nih.gov/protein/gi:";
88     public static final String       NCBI_NUCCORE                     = "http://www.ncbi.nlm.nih.gov/nuccore/";
89     public static final String       NCBI_PROTEIN                     = "http://www.ncbi.nlm.nih.gov/protein/";
90     public static final BigDecimal   NULL_BD                          = new BigDecimal( 0 );
91     public final static String       OS_ARCH                          = System.getProperty( "os.arch" );
92     public final static String       OS_NAME                          = System.getProperty( "os.name" );
93     public final static String       OS_VERSION                       = System.getProperty( "os.version" );
94     public static final String       PDB                              = "http://www.pdb.org/pdb/explore/explore.do?pdbId=";
95     public final static String       UNIPROT_KB                       = "http://www.uniprot.org/uniprot/";
96     public final static double       ZERO_DIFF                        = 1.0E-9;
97     private static final Pattern     PARANTHESESABLE_NH_CHARS_PATTERN = Pattern.compile( "[(),;\\s:\\[\\]]" );
98     static {
99         final DecimalFormatSymbols dfs = new DecimalFormatSymbols();
100         dfs.setDecimalSeparator( '.' );
101         // dfs.setGroupingSeparator( ( char ) 0 );
102         FORMATTER_9 = new DecimalFormat( "#.#########", dfs );
103         FORMATTER_6 = new DecimalFormat( "#.######", dfs );
104         FORMATTER_06 = new DecimalFormat( "0.######", dfs );
105         FORMATTER_3 = new DecimalFormat( "#.###", dfs );
106     }
107
108     private ForesterUtil() {
109     }
110
111     final public static void appendSeparatorIfNotEmpty( final StringBuffer sb, final char separator ) {
112         if ( sb.length() > 0 ) {
113             sb.append( separator );
114         }
115     }
116
117     /**
118      * This calculates a color. If value is equal to min the returned color is
119      * minColor, if value is equal to max the returned color is maxColor,
120      * otherwise a color 'proportional' to value is returned.
121      * 
122      * @param value
123      *            the value 
124      * @param min
125      *            the smallest value 
126      * @param max
127      *            the largest value 
128      * @param minColor
129      *            the color for min
130      * @param maxColor
131      *            the color for max
132      * @return a Color
133      */
134     final public static Color calcColor( double value,
135                                          final double min,
136                                          final double max,
137                                          final Color minColor,
138                                          final Color maxColor ) {
139         if ( value < min ) {
140             value = min;
141         }
142         if ( value > max ) {
143             value = max;
144         }
145         final double x = ForesterUtil.calculateColorFactor( value, max, min );
146         final int red = ForesterUtil.calculateColorComponent( minColor.getRed(), maxColor.getRed(), x );
147         final int green = ForesterUtil.calculateColorComponent( minColor.getGreen(), maxColor.getGreen(), x );
148         final int blue = ForesterUtil.calculateColorComponent( minColor.getBlue(), maxColor.getBlue(), x );
149         return new Color( red, green, blue );
150     }
151
152     /**
153      * This calculates a color. If value is equal to min the returned color is
154      * minColor, if value is equal to max the returned color is maxColor, if
155      * value is equal to mean the returned color is meanColor, otherwise a color
156      * 'proportional' to value is returned -- either between min-mean or
157      * mean-max
158      * 
159      * @param value
160      *            the value
161      * @param min
162      *            the smallest value
163      * @param max
164      *            the largest value 
165      * @param mean
166      *            the mean/median value 
167      * @param minColor
168      *            the color for min
169      * @param maxColor
170      *            the color for max
171      * @param meanColor
172      *            the color for mean
173      * @return a Color
174      */
175     final public static Color calcColor( double value,
176                                          final double min,
177                                          final double max,
178                                          final double mean,
179                                          final Color minColor,
180                                          final Color maxColor,
181                                          final Color meanColor ) {
182         if ( value < min ) {
183             value = min;
184         }
185         if ( value > max ) {
186             value = max;
187         }
188         if ( value < mean ) {
189             final double x = ForesterUtil.calculateColorFactor( value, mean, min );
190             final int red = ForesterUtil.calculateColorComponent( minColor.getRed(), meanColor.getRed(), x );
191             final int green = ForesterUtil.calculateColorComponent( minColor.getGreen(), meanColor.getGreen(), x );
192             final int blue = ForesterUtil.calculateColorComponent( minColor.getBlue(), meanColor.getBlue(), x );
193             return new Color( red, green, blue );
194         }
195         else if ( value > mean ) {
196             final double x = ForesterUtil.calculateColorFactor( value, max, mean );
197             final int red = ForesterUtil.calculateColorComponent( meanColor.getRed(), maxColor.getRed(), x );
198             final int green = ForesterUtil.calculateColorComponent( meanColor.getGreen(), maxColor.getGreen(), x );
199             final int blue = ForesterUtil.calculateColorComponent( meanColor.getBlue(), maxColor.getBlue(), x );
200             return new Color( red, green, blue );
201         }
202         else {
203             return meanColor;
204         }
205     }
206
207     public static int calculateOverlap( final Domain domain, final List<Boolean> covered_positions ) {
208         int overlap_count = 0;
209         for( int i = domain.getFrom(); i <= domain.getTo(); ++i ) {
210             if ( ( i < covered_positions.size() ) && ( covered_positions.get( i ) == true ) ) {
211                 ++overlap_count;
212             }
213         }
214         return overlap_count;
215     }
216
217     final public static String collapseWhiteSpace( final String s ) {
218         return s.replaceAll( "[\\s]+", " " );
219     }
220
221     final public static void collection2file( final File file, final Collection<?> data, final String separator )
222             throws IOException {
223         final Writer writer = new BufferedWriter( new FileWriter( file ) );
224         collection2writer( writer, data, separator );
225         writer.close();
226     }
227
228     final public static void collection2writer( final Writer writer, final Collection<?> data, final String separator )
229             throws IOException {
230         boolean first = true;
231         for( final Object object : data ) {
232             if ( !first ) {
233                 writer.write( separator );
234             }
235             else {
236                 first = false;
237             }
238             writer.write( object.toString() );
239         }
240     }
241
242     final public static String colorToHex( final Color color ) {
243         final String rgb = Integer.toHexString( color.getRGB() );
244         return rgb.substring( 2, rgb.length() );
245     }
246
247     synchronized public static void copyFile( final File in, final File out ) throws IOException {
248         final FileInputStream in_s = new FileInputStream( in );
249         final FileOutputStream out_s = new FileOutputStream( out );
250         try {
251             final byte[] buf = new byte[ 1024 ];
252             int i = 0;
253             while ( ( i = in_s.read( buf ) ) != -1 ) {
254                 out_s.write( buf, 0, i );
255             }
256         }
257         catch ( final IOException e ) {
258             throw e;
259         }
260         finally {
261             if ( in_s != null ) {
262                 in_s.close();
263             }
264             if ( out_s != null ) {
265                 out_s.close();
266             }
267         }
268     }
269
270     final public static int countChars( final String str, final char c ) {
271         int count = 0;
272         for( int i = 0; i < str.length(); ++i ) {
273             if ( str.charAt( i ) == c ) {
274                 ++count;
275             }
276         }
277         return count;
278     }
279
280     final public static BufferedWriter createBufferedWriter( final File file ) throws IOException {
281         if ( file.exists() ) {
282             throw new IOException( "[" + file + "] already exists" );
283         }
284         return new BufferedWriter( new FileWriter( file ) );
285     }
286
287     final public static BufferedWriter createBufferedWriter( final String name ) throws IOException {
288         return new BufferedWriter( new FileWriter( createFileForWriting( name ) ) );
289     }
290
291     final public static EasyWriter createEasyWriter( final File file ) throws IOException {
292         return new EasyWriter( createBufferedWriter( file ) );
293     }
294
295     final public static BufferedWriter createEasyWriter( final String name ) throws IOException {
296         return createEasyWriter( createFileForWriting( name ) );
297     }
298
299     final public static File createFileForWriting( final String name ) throws IOException {
300         final File file = new File( name );
301         if ( file.exists() ) {
302             throw new IOException( "[" + name + "] already exists" );
303         }
304         return file;
305     }
306
307     final public static void ensurePresenceOfDate( final PhylogenyNode node ) {
308         if ( !node.getNodeData().isHasDate() ) {
309             node.getNodeData().setDate( new org.forester.phylogeny.data.Date() );
310         }
311     }
312
313     final public static void ensurePresenceOfDistribution( final PhylogenyNode node ) {
314         if ( !node.getNodeData().isHasDistribution() ) {
315             node.getNodeData().setDistribution( new Distribution( "" ) );
316         }
317     }
318
319     public static void ensurePresenceOfSequence( final PhylogenyNode node ) {
320         if ( !node.getNodeData().isHasSequence() ) {
321             node.getNodeData().setSequence( new Sequence() );
322         }
323     }
324
325     public static void ensurePresenceOfTaxonomy( final PhylogenyNode node ) {
326         if ( !node.getNodeData().isHasTaxonomy() ) {
327             node.getNodeData().setTaxonomy( new Taxonomy() );
328         }
329     }
330
331     public static void fatalError( final String message ) {
332         System.err.println();
333         System.err.println( "error: " + message );
334         System.err.println();
335         System.exit( -1 );
336     }
337
338     public static void fatalError( final String prg_name, final String message ) {
339         System.err.println();
340         System.err.println( "[" + prg_name + "] > " + message );
341         System.err.println();
342         System.exit( -1 );
343     }
344
345     public static void fatalErrorIfFileNotReadable( final File file ) {
346         final String error = isReadableFile( file );
347         if ( !isEmpty( error ) ) {
348             System.err.println();
349             System.err.println( "error: " + error );
350             System.err.println();
351             System.exit( -1 );
352         }
353     }
354
355     public static void fatalErrorIfFileNotReadable( final String prg_name, final File file ) {
356         final String error = isReadableFile( file );
357         if ( !isEmpty( error ) ) {
358             System.err.println();
359             System.err.println( "[" + prg_name + "] > " + error );
360             System.err.println();
361             System.exit( -1 );
362         }
363     }
364
365     public static String[][] file22dArray( final File file ) throws IOException {
366         final List<String> list = new ArrayList<String>();
367         final BufferedReader in = new BufferedReader( new FileReader( file ) );
368         String str;
369         while ( ( str = in.readLine() ) != null ) {
370             str = str.trim();
371             if ( ( str.length() > 0 ) && !str.startsWith( "#" ) ) {
372                 list.add( str );
373             }
374         }
375         in.close();
376         final String[][] ary = new String[ list.size() ][ 2 ];
377         final Pattern pa = Pattern.compile( "(\\S+)\\s+(\\S+)" );
378         int i = 0;
379         for( final String s : list ) {
380             final Matcher m = pa.matcher( s );
381             if ( m.matches() ) {
382                 ary[ i ][ 0 ] = m.group( 1 );
383                 ary[ i ][ 1 ] = m.group( 2 );
384                 ++i;
385             }
386             else {
387                 throw new IOException( "unexpcted format: " + s );
388             }
389         }
390         return ary;
391     }
392
393     public static String[] file2array( final File file ) throws IOException {
394         final List<String> list = file2list( file );
395         final String[] ary = new String[ list.size() ];
396         int i = 0;
397         for( final String s : list ) {
398             ary[ i++ ] = s;
399         }
400         return ary;
401     }
402
403     final public static List<String> file2list( final File file ) throws IOException {
404         final List<String> list = new ArrayList<String>();
405         final BufferedReader in = new BufferedReader( new FileReader( file ) );
406         String str;
407         while ( ( str = in.readLine() ) != null ) {
408             str = str.trim();
409             if ( ( str.length() > 0 ) && !str.startsWith( "#" ) ) {
410                 for( final String s : splitString( str ) ) {
411                     list.add( s );
412                 }
413             }
414         }
415         in.close();
416         return list;
417     }
418
419     final public static SortedSet<String> file2set( final File file ) throws IOException {
420         final SortedSet<String> set = new TreeSet<String>();
421         final BufferedReader in = new BufferedReader( new FileReader( file ) );
422         String str;
423         while ( ( str = in.readLine() ) != null ) {
424             str = str.trim();
425             if ( ( str.length() > 0 ) && !str.startsWith( "#" ) ) {
426                 for( final String s : splitString( str ) ) {
427                     set.add( s );
428                 }
429             }
430         }
431         in.close();
432         return set;
433     }
434
435     final public static String getCurrentDateTime() {
436         final DateFormat format = new SimpleDateFormat( "yyyy/MM/dd HH:mm:ss" );
437         return format.format( new Date() );
438     }
439
440     final public static String getFileSeparator() {
441         return ForesterUtil.FILE_SEPARATOR;
442     }
443
444     final public static String getFirstLine( final Object source ) throws FileNotFoundException, IOException {
445         BufferedReader reader = null;
446         if ( source instanceof File ) {
447             final File f = ( File ) source;
448             if ( !f.exists() ) {
449                 throw new IOException( "[" + f.getAbsolutePath() + "] does not exist" );
450             }
451             else if ( !f.isFile() ) {
452                 throw new IOException( "[" + f.getAbsolutePath() + "] is not a file" );
453             }
454             else if ( !f.canRead() ) {
455                 throw new IOException( "[" + f.getAbsolutePath() + "] is not a readable" );
456             }
457             reader = new BufferedReader( new FileReader( f ) );
458         }
459         else if ( source instanceof InputStream ) {
460             reader = new BufferedReader( new InputStreamReader( ( InputStream ) source ) );
461         }
462         else if ( source instanceof String ) {
463             reader = new BufferedReader( new StringReader( ( String ) source ) );
464         }
465         else if ( source instanceof StringBuffer ) {
466             reader = new BufferedReader( new StringReader( source.toString() ) );
467         }
468         else if ( source instanceof URL ) {
469             final URLConnection url_connection = ( ( URL ) source ).openConnection();
470             url_connection.setDefaultUseCaches( false );
471             reader = new BufferedReader( new InputStreamReader( url_connection.getInputStream() ) );
472         }
473         else {
474             throw new IllegalArgumentException( "dont know how to read [" + source.getClass() + "]" );
475         }
476         String line;
477         while ( ( line = reader.readLine() ) != null ) {
478             line = line.trim();
479             if ( !ForesterUtil.isEmpty( line ) ) {
480                 if ( reader != null ) {
481                     reader.close();
482                 }
483                 return line;
484             }
485         }
486         if ( reader != null ) {
487             reader.close();
488         }
489         return line;
490     }
491
492     final public static String getForesterLibraryInformation() {
493         return "forester " + ForesterConstants.FORESTER_VERSION + " (" + ForesterConstants.FORESTER_DATE + ")";
494     }
495
496     final public static String getLineSeparator() {
497         return ForesterUtil.LINE_SEPARATOR;
498     }
499
500     final public static void increaseCountingMap( final Map<String, Integer> counting_map, final String item_name ) {
501         if ( !counting_map.containsKey( item_name ) ) {
502             counting_map.put( item_name, 1 );
503         }
504         else {
505             counting_map.put( item_name, counting_map.get( item_name ) + 1 );
506         }
507     }
508
509     final public static boolean isEmpty( final List<?> l ) {
510         if ( ( l == null ) || l.isEmpty() ) {
511             return true;
512         }
513         for( final Object o : l ) {
514             if ( o != null ) {
515                 return false;
516             }
517         }
518         return true;
519     }
520
521     final public static boolean isEmpty( final Set<?> s ) {
522         if ( ( s == null ) || s.isEmpty() ) {
523             return true;
524         }
525         for( final Object o : s ) {
526             if ( o != null ) {
527                 return false;
528             }
529         }
530         return true;
531     }
532
533     final public static boolean isEmpty( final String s ) {
534         return ( ( s == null ) || ( s.length() < 1 ) );
535     }
536
537     /**
538      * Returns true is Domain domain falls in an uninterrupted stretch of
539      * covered positions.
540      * 
541      * @param domain
542      * @param covered_positions
543      * @return
544      */
545     public static boolean isEngulfed( final Domain domain, final List<Boolean> covered_positions ) {
546         for( int i = domain.getFrom(); i <= domain.getTo(); ++i ) {
547             if ( ( i >= covered_positions.size() ) || ( covered_positions.get( i ) != true ) ) {
548                 return false;
549             }
550         }
551         return true;
552     }
553
554     final public static boolean isEqual( final double a, final double b ) {
555         return ( ( Math.abs( a - b ) ) < ZERO_DIFF );
556     }
557
558     final public static boolean isEven( final int n ) {
559         return ( n % 2 ) == 0;
560     }
561
562     /**
563      * This determines whether String[] a and String[] b have at least one
564      * String in common (intersect). Returns false if at least one String[] is
565      * null or empty.
566      * 
567      * @param a
568      *            a String[] b a String[]
569      * @return true if both a and b or not empty or null and contain at least
570      *         one element in common false otherwise
571      */
572     final public static boolean isIntersecting( final String[] a, final String[] b ) {
573         if ( ( a == null ) || ( b == null ) ) {
574             return false;
575         }
576         if ( ( a.length < 1 ) || ( b.length < 1 ) ) {
577             return false;
578         }
579         for( final String ai : a ) {
580             for( final String element : b ) {
581                 if ( ( ai != null ) && ( element != null ) && ai.equals( element ) ) {
582                     return true;
583                 }
584             }
585         }
586         return false;
587     }
588
589     final public static double isLargerOrEqualToZero( final double d ) {
590         if ( d > 0.0 ) {
591             return d;
592         }
593         else {
594             return 0.0;
595         }
596     }
597
598     public final static boolean isMac() {
599         try {
600             return OS_NAME.toLowerCase().startsWith( "mac" );
601         }
602         catch ( final Exception e ) {
603             ForesterUtil.printWarningMessage( Constants.PRG_NAME, "minor error: " + e );
604             return false;
605         }
606     }
607
608     final public static boolean isNull( final BigDecimal s ) {
609         return ( ( s == null ) || ( s.compareTo( NULL_BD ) == 0 ) );
610     }
611
612     final public static String isReadableFile( final File f ) {
613         if ( !f.exists() ) {
614             return "file [" + f + "] does not exist";
615         }
616         if ( f.isDirectory() ) {
617             return "[" + f + "] is a directory";
618         }
619         if ( !f.isFile() ) {
620             return "[" + f + "] is not a file";
621         }
622         if ( !f.canRead() ) {
623             return "file [" + f + "] is not readable";
624         }
625         if ( f.length() < 1 ) {
626             return "file [" + f + "] is empty";
627         }
628         return null;
629     }
630
631     final public static String isReadableFile( final String s ) {
632         return isReadableFile( new File( s ) );
633     }
634
635     public final static boolean isWindows() {
636         try {
637             return OS_NAME.toLowerCase().indexOf( "win" ) > -1;
638         }
639         catch ( final Exception e ) {
640             ForesterUtil.printWarningMessage( Constants.PRG_NAME, "minor error: " + e );
641             return false;
642         }
643     }
644
645     final public static String isWritableFile( final File f ) {
646         if ( f.isDirectory() ) {
647             return "[" + f + "] is a directory";
648         }
649         if ( f.exists() ) {
650             return "[" + f + "] already exists";
651         }
652         return null;
653     }
654
655     /**
656      * Helper for method "stringToColor".
657      * <p>
658      * (Last modified: 12/20/03)
659      */
660     final public static int limitRangeForColor( int i ) {
661         if ( i > 255 ) {
662             i = 255;
663         }
664         else if ( i < 0 ) {
665             i = 0;
666         }
667         return i;
668     }
669
670     final public static SortedMap<Object, Integer> listToSortedCountsMap( final List<?> list ) {
671         final SortedMap<Object, Integer> map = new TreeMap<Object, Integer>();
672         for( final Object key : list ) {
673             if ( !map.containsKey( key ) ) {
674                 map.put( key, 1 );
675             }
676             else {
677                 map.put( key, map.get( key ) + 1 );
678             }
679         }
680         return map;
681     }
682
683     final public static void map2file( final File file,
684                                        final Map<?, ?> data,
685                                        final String entry_separator,
686                                        final String data_separator ) throws IOException {
687         final Writer writer = new BufferedWriter( new FileWriter( file ) );
688         map2writer( writer, data, entry_separator, data_separator );
689         writer.close();
690     }
691
692     final public static void map2writer( final Writer writer,
693                                          final Map<?, ?> data,
694                                          final String entry_separator,
695                                          final String data_separator ) throws IOException {
696         boolean first = true;
697         for( final Entry<?, ?> entry : data.entrySet() ) {
698             if ( !first ) {
699                 writer.write( data_separator );
700             }
701             else {
702                 first = false;
703             }
704             writer.write( entry.getKey().toString() );
705             writer.write( entry_separator );
706             writer.write( entry.getValue().toString() );
707         }
708     }
709
710     final public static StringBuffer mapToStringBuffer( final Map<Object, Object> map, final String key_value_separator ) {
711         final StringBuffer sb = new StringBuffer();
712         for( final Object key : map.keySet() ) {
713             sb.append( key.toString() );
714             sb.append( key_value_separator );
715             sb.append( map.get( key ).toString() );
716             sb.append( ForesterUtil.getLineSeparator() );
717         }
718         return sb;
719     }
720
721     final public static String normalizeString( final String s,
722                                                 final int length,
723                                                 final boolean left_pad,
724                                                 final char pad_char ) {
725         if ( s.length() > length ) {
726             return s.substring( 0, length );
727         }
728         else {
729             final StringBuffer pad = new StringBuffer( length - s.length() );
730             for( int i = 0; i < ( length - s.length() ); ++i ) {
731                 pad.append( pad_char );
732             }
733             if ( left_pad ) {
734                 return pad + s;
735             }
736             else {
737                 return s + pad;
738             }
739         }
740     }
741
742     public final static Color obtainColorDependingOnTaxonomyGroup( final String tax_group ) {
743         if ( !ForesterUtil.isEmpty( tax_group ) ) {
744             if ( tax_group.equals( TaxonomyGroups.DEUTEROSTOMIA ) ) {
745                 return TaxonomyColors.DEUTEROSTOMIA_COLOR;
746             }
747             else if ( tax_group.equals( TaxonomyGroups.PROTOSTOMIA ) ) {
748                 return TaxonomyColors.PROTOSTOMIA_COLOR;
749             }
750             else if ( tax_group.equals( TaxonomyGroups.CNIDARIA ) ) {
751                 return TaxonomyColors.CNIDARIA_COLOR;
752             }
753             else if ( tax_group.equals( TaxonomyGroups.PLACOZOA ) ) {
754                 return TaxonomyColors.PLACOZOA_COLOR;
755             }
756             else if ( tax_group.equals( TaxonomyGroups.CTENOPHORA ) ) {
757                 return TaxonomyColors.CTENOPHORA_COLOR;
758             }
759             else if ( tax_group.equals( TaxonomyGroups.PORIFERA ) ) {
760                 return TaxonomyColors.PORIFERA_COLOR;
761             }
762             else if ( tax_group.equals( TaxonomyGroups.CHOANOFLAGELLIDA ) ) {
763                 return TaxonomyColors.CHOANOFLAGELLIDA;
764             }
765             else if ( tax_group.equals( TaxonomyGroups.ICHTHYOPHONIDA_FILASTEREA ) ) {
766                 return TaxonomyColors.ICHTHYOSPOREA_AND_FILASTEREA;
767             }
768             else if ( tax_group.equals( TaxonomyGroups.DIKARYA ) ) {
769                 return TaxonomyColors.DIKARYA_COLOR;
770             }
771             else if ( tax_group.equalsIgnoreCase( TaxonomyGroups.FUNGI )
772                     || tax_group.equalsIgnoreCase( TaxonomyGroups.OTHER_FUNGI ) ) {
773                 return TaxonomyColors.OTHER_FUNGI_COLOR;
774             }
775             else if ( tax_group.equals( TaxonomyGroups.NUCLEARIIDAE_AND_FONTICULA_GROUP ) ) {
776                 return TaxonomyColors.NUCLEARIIDAE_AND_FONTICULA_GROUP_COLOR;
777             }
778             else if ( tax_group.equals( TaxonomyGroups.AMOEBOZOA ) ) {
779                 return TaxonomyColors.AMOEBOZOA_COLOR;
780             }
781             else if ( tax_group.equals( TaxonomyGroups.EMBRYOPHYTA ) ) {
782                 return TaxonomyColors.EMBRYOPHYTA_COLOR;
783             }
784             else if ( tax_group.equals( TaxonomyGroups.CHLOROPHYTA ) ) {
785                 return TaxonomyColors.CHLOROPHYTA_COLOR;
786             }
787             else if ( tax_group.equals( TaxonomyGroups.RHODOPHYTA ) ) {
788                 return TaxonomyColors.RHODOPHYTA_COLOR;
789             }
790             else if ( tax_group.equals( TaxonomyGroups.HACROBIA ) ) {
791                 return TaxonomyColors.HACROBIA_COLOR;
792             }
793             else if ( tax_group.equals( TaxonomyGroups.GLAUCOCYSTOPHYCEAE ) ) {
794                 return TaxonomyColors.GLAUCOPHYTA_COLOR;
795             }
796             else if ( tax_group.equals( TaxonomyGroups.STRAMENOPILES ) ) {
797                 return TaxonomyColors.STRAMENOPILES_COLOR;
798             }
799             else if ( tax_group.equals( TaxonomyGroups.ALVEOLATA ) ) {
800                 return TaxonomyColors.ALVEOLATA_COLOR;
801             }
802             else if ( tax_group.equals( TaxonomyGroups.RHIZARIA ) ) {
803                 return TaxonomyColors.RHIZARIA_COLOR;
804             }
805             else if ( tax_group.equals( TaxonomyGroups.EXCAVATA ) ) {
806                 return TaxonomyColors.EXCAVATA_COLOR;
807             }
808             else if ( tax_group.equals( TaxonomyGroups.APUSOZOA ) ) {
809                 return TaxonomyColors.APUSOZOA_COLOR;
810             }
811             else if ( tax_group.equals( TaxonomyGroups.ARCHAEA ) ) {
812                 return TaxonomyColors.ARCHAEA_COLOR;
813             }
814             else if ( tax_group.equals( TaxonomyGroups.BACTERIA ) ) {
815                 return TaxonomyColors.BACTERIA_COLOR;
816             }
817         }
818         return null;
819     }
820
821     public final static String obtainNormalizedTaxonomyGroup( final String tax ) {
822         if ( tax.equalsIgnoreCase( TaxonomyGroups.DEUTEROSTOMIA ) ) {
823             return TaxonomyGroups.DEUTEROSTOMIA;
824         }
825         else if ( tax.equalsIgnoreCase( TaxonomyGroups.PROTOSTOMIA ) ) {
826             return TaxonomyGroups.PROTOSTOMIA;
827         }
828         else if ( tax.equalsIgnoreCase( TaxonomyGroups.CNIDARIA ) ) {
829             return TaxonomyGroups.CNIDARIA;
830         }
831         else if ( tax.toLowerCase().startsWith( "trichoplax" ) || tax.equalsIgnoreCase( TaxonomyGroups.PLACOZOA ) ) {
832             return TaxonomyGroups.PLACOZOA;
833         }
834         else if ( tax.toLowerCase().startsWith( "mnemiopsis" ) || tax.equalsIgnoreCase( TaxonomyGroups.CTENOPHORA ) ) {
835             return TaxonomyGroups.CTENOPHORA;
836         }
837         else if ( tax.toLowerCase().startsWith( "amphimedon" ) || tax.equalsIgnoreCase( TaxonomyGroups.PORIFERA ) ) {
838             return TaxonomyGroups.PORIFERA;
839         }
840         else if ( tax.equalsIgnoreCase( "codonosigidae" ) || tax.equalsIgnoreCase( TaxonomyGroups.CHOANOFLAGELLIDA ) ) {
841             return TaxonomyGroups.CHOANOFLAGELLIDA;
842         }
843         else if ( tax.toLowerCase().startsWith( TaxonomyGroups.ICHTHYOPHONIDA_FILASTEREA )
844                 || tax.toLowerCase().startsWith( "ichthyophonida and filasterea" )
845                 || tax.toLowerCase().startsWith( "ichthyosporea & filasterea" )
846                 || tax.toLowerCase().startsWith( "ichthyosporea and filasterea" ) ) {
847             return TaxonomyGroups.ICHTHYOPHONIDA_FILASTEREA;
848         }
849         else if ( tax.equalsIgnoreCase( TaxonomyGroups.DIKARYA ) ) {
850             return TaxonomyGroups.DIKARYA;
851         }
852         else if ( tax.equalsIgnoreCase( TaxonomyGroups.FUNGI ) || tax.equalsIgnoreCase( TaxonomyGroups.OTHER_FUNGI ) ) {
853             return TaxonomyGroups.OTHER_FUNGI;
854         }
855         else if ( tax.toLowerCase().startsWith( "nucleariidae and fonticula" ) ) {
856             return TaxonomyGroups.NUCLEARIIDAE_AND_FONTICULA_GROUP;
857         }
858         else if ( tax.equalsIgnoreCase( TaxonomyGroups.AMOEBOZOA ) ) {
859             return TaxonomyGroups.AMOEBOZOA;
860         }
861         else if ( tax.equalsIgnoreCase( TaxonomyGroups.EMBRYOPHYTA ) ) {
862             return TaxonomyGroups.EMBRYOPHYTA;
863         }
864         else if ( tax.equalsIgnoreCase( TaxonomyGroups.CHLOROPHYTA ) ) {
865             return TaxonomyGroups.CHLOROPHYTA;
866         }
867         else if ( tax.equalsIgnoreCase( TaxonomyGroups.RHODOPHYTA ) ) {
868             return TaxonomyGroups.RHODOPHYTA;
869         }
870         else if ( tax.toLowerCase().startsWith( TaxonomyGroups.HACROBIA ) ) {
871             return TaxonomyGroups.HACROBIA;
872         }
873         else if ( tax.equalsIgnoreCase( TaxonomyGroups.GLAUCOCYSTOPHYCEAE ) || tax.equalsIgnoreCase( "glaucophyta" ) ) {
874             return TaxonomyGroups.GLAUCOCYSTOPHYCEAE;
875         }
876         else if ( tax.equalsIgnoreCase( TaxonomyGroups.STRAMENOPILES ) ) {
877             return TaxonomyGroups.STRAMENOPILES;
878         }
879         else if ( tax.equalsIgnoreCase( TaxonomyGroups.ALVEOLATA ) ) {
880             return TaxonomyGroups.ALVEOLATA;
881         }
882         else if ( tax.equalsIgnoreCase( TaxonomyGroups.RHIZARIA ) ) {
883             return TaxonomyGroups.RHIZARIA;
884         }
885         else if ( tax.equalsIgnoreCase( TaxonomyGroups.EXCAVATA ) ) {
886             return TaxonomyGroups.EXCAVATA;
887         }
888         else if ( tax.equalsIgnoreCase( TaxonomyGroups.APUSOZOA ) ) {
889             return TaxonomyGroups.APUSOZOA;
890         }
891         else if ( tax.equalsIgnoreCase( TaxonomyGroups.ARCHAEA ) ) {
892             return TaxonomyGroups.ARCHAEA;
893         }
894         else if ( tax.equalsIgnoreCase( TaxonomyGroups.BACTERIA ) ) {
895             return TaxonomyGroups.BACTERIA;
896         }
897         return null;
898     }
899
900     final public static BufferedReader obtainReader( final Object source ) throws IOException, FileNotFoundException {
901         BufferedReader reader = null;
902         if ( source instanceof File ) {
903             final File f = ( File ) source;
904             if ( !f.exists() ) {
905                 throw new IOException( "\"" + f.getAbsolutePath() + "\" does not exist" );
906             }
907             else if ( !f.isFile() ) {
908                 throw new IOException( "\"" + f.getAbsolutePath() + "\" is not a file" );
909             }
910             else if ( !f.canRead() ) {
911                 throw new IOException( "\"" + f.getAbsolutePath() + "\" is not a readable" );
912             }
913             reader = new BufferedReader( new FileReader( f ) );
914         }
915         else if ( source instanceof InputStream ) {
916             reader = new BufferedReader( new InputStreamReader( ( InputStream ) source ) );
917         }
918         else if ( source instanceof String ) {
919             reader = new BufferedReader( new StringReader( ( String ) source ) );
920         }
921         else if ( source instanceof StringBuffer ) {
922             reader = new BufferedReader( new StringReader( source.toString() ) );
923         }
924         else {
925             throw new IllegalArgumentException( "attempt to parse object of type [" + source.getClass()
926                     + "] (can only parse objects of type File, InputStream, String, or StringBuffer)" );
927         }
928         return reader;
929     }
930
931     public final static void outOfMemoryError( final OutOfMemoryError e ) {
932         System.err.println();
933         System.err.println( "Java memory allocation might be too small, try \"-Xmx2048m\" java command line option" );
934         System.err.println();
935         e.printStackTrace( System.err );
936         System.err.println();
937         System.exit( -1 );
938     }
939
940     final public static StringBuffer pad( final double number, final int size, final char pad, final boolean left_pad ) {
941         return pad( new StringBuffer( number + "" ), size, pad, left_pad );
942     }
943
944     final public static StringBuffer pad( final String string, final int size, final char pad, final boolean left_pad ) {
945         return pad( new StringBuffer( string ), size, pad, left_pad );
946     }
947
948     final public static StringBuffer pad( final StringBuffer string,
949                                           final int size,
950                                           final char pad,
951                                           final boolean left_pad ) {
952         final StringBuffer padding = new StringBuffer();
953         final int s = size - string.length();
954         if ( s < 1 ) {
955             return new StringBuffer( string.substring( 0, size ) );
956         }
957         for( int i = 0; i < s; ++i ) {
958             padding.append( pad );
959         }
960         if ( left_pad ) {
961             return padding.append( string );
962         }
963         else {
964             return string.append( padding );
965         }
966     }
967
968     final public static double parseDouble( final String str ) throws ParseException {
969         if ( ForesterUtil.isEmpty( str ) ) {
970             return 0.0;
971         }
972         return Double.parseDouble( str );
973     }
974
975     final public static int parseInt( final String str ) throws ParseException {
976         if ( ForesterUtil.isEmpty( str ) ) {
977             return 0;
978         }
979         return Integer.parseInt( str );
980     }
981
982     final public static void printArray( final Object[] a ) {
983         for( int i = 0; i < a.length; ++i ) {
984             System.out.println( "[" + i + "]=" + a[ i ] );
985         }
986     }
987
988     final public static void printCountingMap( final Map<String, Integer> counting_map ) {
989         for( final String key : counting_map.keySet() ) {
990             System.out.println( key + ": " + counting_map.get( key ) );
991         }
992     }
993
994     final public static void printErrorMessage( final String prg_name, final String message ) {
995         System.err.println( "[" + prg_name + "] > error: " + message );
996     }
997
998     final public static void printProgramInformation( final String prg_name, final String prg_version, final String date ) {
999         final int l = prg_name.length() + prg_version.length() + date.length() + 4;
1000         System.out.println();
1001         System.out.println( prg_name + " " + prg_version + " (" + date + ")" );
1002         for( int i = 0; i < l; ++i ) {
1003             System.out.print( "_" );
1004         }
1005         System.out.println();
1006     }
1007
1008     final public static void printProgramInformation( final String prg_name,
1009                                                       final String prg_version,
1010                                                       final String date,
1011                                                       final String email,
1012                                                       final String www ) {
1013         printProgramInformation( prg_name, null, prg_version, date, email, www, null );
1014     }
1015
1016     final public static void printProgramInformation( final String prg_name,
1017                                                       final String desc,
1018                                                       final String prg_version,
1019                                                       final String date,
1020                                                       final String email,
1021                                                       final String www,
1022                                                       final String based_on ) {
1023         String my_prg_name = new String( prg_name );
1024         if ( !ForesterUtil.isEmpty( desc ) ) {
1025             my_prg_name += ( " - " + desc );
1026         }
1027         final int l = my_prg_name.length() + prg_version.length() + date.length() + 4;
1028         System.out.println();
1029         System.out.println( my_prg_name + " " + prg_version + " (" + date + ")" );
1030         for( int i = 0; i < l; ++i ) {
1031             System.out.print( "_" );
1032         }
1033         System.out.println();
1034         System.out.println();
1035         System.out.println( "WWW     : " + www );
1036         System.out.println( "Contact : " + email );
1037         if ( !ForesterUtil.isEmpty( based_on ) ) {
1038             System.out.println( "Based on: " + based_on );
1039         }
1040         if ( !ForesterUtil.isEmpty( ForesterUtil.JAVA_VERSION ) && !ForesterUtil.isEmpty( ForesterUtil.JAVA_VENDOR ) ) {
1041             System.out.println();
1042             System.out.println( "[running on Java " + ForesterUtil.JAVA_VERSION + " " + ForesterUtil.JAVA_VENDOR + "]" );
1043         }
1044         System.out.println();
1045     }
1046
1047     final public static void printWarningMessage( final String prg_name, final String message ) {
1048         System.out.println( "[" + prg_name + "] > warning: " + message );
1049     }
1050
1051     final public static void programMessage( final String prg_name, final String message ) {
1052         System.out.println( "[" + prg_name + "] > " + message );
1053     }
1054
1055     /**
1056      * 
1057      * Example regarding engulfment: ------------0.1 ----------0.2 --0.3 =>
1058      * domain with 0.3 is ignored
1059      * 
1060      * -----------0.1 ----------0.2 --0.3 => domain with 0.3 is ignored
1061      * 
1062      * 
1063      * ------------0.1 ----------0.3 --0.2 => domains with 0.3 and 0.2 are _not_
1064      * ignored
1065      * 
1066      * @param max_allowed_overlap
1067      *            maximal allowed overlap (inclusive) to be still considered not
1068      *            overlapping (zero or negative value to allow any overlap)
1069      * @param remove_engulfed_domains
1070      *            to remove domains which are completely engulfed by coverage of
1071      *            domains with better support
1072      * @param protein
1073      * @return
1074      */
1075     public static Protein removeOverlappingDomains( final int max_allowed_overlap,
1076                                                     final boolean remove_engulfed_domains,
1077                                                     final Protein protein ) {
1078         final Protein pruned_protein = new BasicProtein( protein.getProteinId().getId(), protein.getSpecies()
1079                 .getSpeciesId(), protein.getLength() );
1080         final List<Domain> sorted = SurfacingUtil.sortDomainsWithAscendingConfidenceValues( protein );
1081         final List<Boolean> covered_positions = new ArrayList<Boolean>();
1082         for( final Domain domain : sorted ) {
1083             if ( ( ( max_allowed_overlap < 0 ) || ( ForesterUtil.calculateOverlap( domain, covered_positions ) <= max_allowed_overlap ) )
1084                     && ( !remove_engulfed_domains || !isEngulfed( domain, covered_positions ) ) ) {
1085                 final int covered_positions_size = covered_positions.size();
1086                 for( int i = covered_positions_size; i < domain.getFrom(); ++i ) {
1087                     covered_positions.add( false );
1088                 }
1089                 final int new_covered_positions_size = covered_positions.size();
1090                 for( int i = domain.getFrom(); i <= domain.getTo(); ++i ) {
1091                     if ( i < new_covered_positions_size ) {
1092                         covered_positions.set( i, true );
1093                     }
1094                     else {
1095                         covered_positions.add( true );
1096                     }
1097                 }
1098                 pruned_protein.addProteinDomain( domain );
1099             }
1100         }
1101         return pruned_protein;
1102     }
1103
1104     final public static String removeSuffix( final String file_name ) {
1105         final int i = file_name.lastIndexOf( '.' );
1106         if ( i > 1 ) {
1107             return file_name.substring( 0, i );
1108         }
1109         return file_name;
1110     }
1111
1112     /**
1113      * Removes all white space from String s.
1114      * 
1115      * @return String s with white space removed
1116      */
1117     final public static String removeWhiteSpace( String s ) {
1118         int i;
1119         for( i = 0; i <= ( s.length() - 1 ); i++ ) {
1120             if ( ( s.charAt( i ) == ' ' ) || ( s.charAt( i ) == '\t' ) || ( s.charAt( i ) == '\n' )
1121                     || ( s.charAt( i ) == '\r' ) ) {
1122                 s = s.substring( 0, i ) + s.substring( i + 1 );
1123                 i--;
1124             }
1125         }
1126         return s;
1127     }
1128
1129     final public static String replaceIllegalNhxCharacters( final String nhx ) {
1130         if ( nhx == null ) {
1131             return "";
1132         }
1133         return nhx.trim().replaceAll( "[\\[\\]']+", "_" );
1134     }
1135
1136     final public static double round( final double value, final int decimal_place ) {
1137         BigDecimal bd = new BigDecimal( value );
1138         bd = bd.setScale( decimal_place, BigDecimal.ROUND_HALF_UP );
1139         return bd.doubleValue();
1140     }
1141
1142     /**
1143      * Rounds d to an int.
1144      */
1145     final public static int roundToInt( final double d ) {
1146         return ( int ) ( d + 0.5 );
1147     }
1148
1149     final public static int roundToInt( final float f ) {
1150         return ( int ) ( f + 0.5f );
1151     }
1152
1153     final public static short roundToShort( final double d ) {
1154         return ( short ) ( d + 0.5 );
1155     }
1156
1157     final public static String sanitizeString( final String s ) {
1158         if ( s == null ) {
1159             return "";
1160         }
1161         else {
1162             return s.trim();
1163         }
1164     }
1165
1166     public final static StringBuilder santitizeStringForNH( String data ) {
1167         data = data.replaceAll( "\\s+", " " ).trim();
1168         final StringBuilder sb = new StringBuilder();
1169         if ( data.length() > 0 ) {
1170             final boolean single_pars = data.indexOf( '\'' ) > -1;
1171             final boolean double_pars = data.indexOf( '"' ) > -1;
1172             if ( single_pars && double_pars ) {
1173                 data = data.replace( '\'', '`' );
1174                 sb.append( '\'' );
1175                 sb.append( data );
1176                 sb.append( '\'' );
1177             }
1178             else if ( single_pars ) {
1179                 sb.append( '"' );
1180                 sb.append( data );
1181                 sb.append( '"' );
1182             }
1183             else if ( PARANTHESESABLE_NH_CHARS_PATTERN.matcher( data ).find() ) {
1184                 sb.append( '\'' );
1185                 sb.append( data );
1186                 sb.append( '\'' );
1187             }
1188             else {
1189                 sb.append( data );
1190             }
1191         }
1192         return sb;
1193     }
1194
1195     public static boolean seqIsLikelyToBeAa( final String s ) {
1196         final String seq = s.toLowerCase();
1197         if ( ( seq.indexOf( 'r' ) > -1 ) || ( seq.indexOf( 'd' ) > -1 ) || ( seq.indexOf( 'e' ) > -1 )
1198                 || ( seq.indexOf( 'q' ) > -1 ) || ( seq.indexOf( 'h' ) > -1 ) || ( seq.indexOf( 'k' ) > -1 )
1199                 || ( seq.indexOf( 'w' ) > -1 ) || ( seq.indexOf( 's' ) > -1 ) || ( seq.indexOf( 'm' ) > -1 )
1200                 || ( seq.indexOf( 'p' ) > -1 ) || ( seq.indexOf( 'v' ) > -1 ) ) {
1201             return true;
1202         }
1203         return false;
1204     }
1205
1206     final public static String stringArrayToString( final String[] a ) {
1207         return stringArrayToString( a, ", " );
1208     }
1209
1210     final public static String stringArrayToString( final String[] a, final String separator ) {
1211         final StringBuilder sb = new StringBuilder();
1212         if ( ( a != null ) && ( a.length > 0 ) ) {
1213             for( int i = 0; i < ( a.length - 1 ); ++i ) {
1214                 sb.append( a[ i ] + separator );
1215             }
1216             sb.append( a[ a.length - 1 ] );
1217         }
1218         return sb.toString();
1219     }
1220
1221     final public static String[] stringListToArray( final List<String> list ) {
1222         if ( list != null ) {
1223             final String[] str = new String[ list.size() ];
1224             int i = 0;
1225             for( final String l : list ) {
1226                 str[ i++ ] = l;
1227             }
1228             return str;
1229         }
1230         return null;
1231     }
1232
1233     final public static String stringListToString( final List<String> l, final String separator ) {
1234         final StringBuilder sb = new StringBuilder();
1235         if ( ( l != null ) && ( l.size() > 0 ) ) {
1236             for( int i = 0; i < ( l.size() - 1 ); ++i ) {
1237                 sb.append( l.get( i ) + separator );
1238             }
1239             sb.append( l.get( l.size() - 1 ) );
1240         }
1241         return sb.toString();
1242     }
1243
1244     final public static String[] stringSetToArray( final Set<String> strings ) {
1245         final String[] str_array = new String[ strings.size() ];
1246         int i = 0;
1247         for( final String e : strings ) {
1248             str_array[ i++ ] = e;
1249         }
1250         return str_array;
1251     }
1252
1253     final public static void unexpectedFatalError( final Error e ) {
1254         System.err.println();
1255         System.err.println( "unexpected error: should not have occured! Please contact program author(s)." );
1256         e.printStackTrace( System.err );
1257         System.err.println();
1258         System.exit( -1 );
1259     }
1260
1261     final public static void unexpectedFatalError( final Exception e ) {
1262         System.err.println();
1263         System.err.println( "unexpected exception: should not have occured! Please contact program author(s)." );
1264         e.printStackTrace( System.err );
1265         System.err.println();
1266         System.exit( -1 );
1267     }
1268
1269     final public static void unexpectedFatalError( final String message ) {
1270         System.err.println();
1271         System.err.println( "unexpected error: should not have occured! Please contact program author(s)." );
1272         System.err.println( message );
1273         System.err.println();
1274         System.exit( -1 );
1275     }
1276
1277     final public static void unexpectedFatalError( final String prg_name, final Exception e ) {
1278         System.err.println();
1279         System.err.println( "[" + prg_name
1280                 + "] > unexpected error; should not have occured! Please contact program author(s)." );
1281         e.printStackTrace( System.err );
1282         System.err.println();
1283         System.exit( -1 );
1284     }
1285
1286     final public static void unexpectedFatalError( final String prg_name, final String message ) {
1287         System.err.println();
1288         System.err.println( "[" + prg_name
1289                 + "] > unexpected error: should not have occured! Please contact program author(s)." );
1290         System.err.println( message );
1291         System.err.println();
1292         System.exit( -1 );
1293     }
1294
1295     final public static void unexpectedFatalError( final String prg_name, final String message, final Exception e ) {
1296         System.err.println();
1297         System.err.println( "[" + prg_name
1298                 + "] > unexpected error: should not have occured! Please contact program author(s)." );
1299         System.err.println( message );
1300         e.printStackTrace( System.err );
1301         System.err.println();
1302         System.exit( -1 );
1303     }
1304
1305     public final static void updateProgress( final double progress_percentage ) {
1306         final int width = 50;
1307         System.out.print( "\r[" );
1308         int i = 0;
1309         for( ; i <= ForesterUtil.roundToInt( progress_percentage * width ); i++ ) {
1310             System.out.print( "." );
1311         }
1312         for( ; i < width; i++ ) {
1313             System.out.print( " " );
1314         }
1315         System.out.print( "]" );
1316     }
1317
1318     public final static void updateProgress( final int i, final DecimalFormat f ) {
1319         System.out.print( "\r[" + f.format( i ) + "]" );
1320     }
1321
1322     public final static String wordWrap( final String str, final int width ) {
1323         final StringBuilder sb = new StringBuilder( str );
1324         int start = 0;
1325         int ls = -1;
1326         int i = 0;
1327         while ( i < sb.length() ) {
1328             if ( sb.charAt( i ) == ' ' ) {
1329                 ls = i;
1330             }
1331             if ( sb.charAt( i ) == '\n' ) {
1332                 ls = -1;
1333                 start = i + 1;
1334             }
1335             if ( i > ( ( start + width ) - 1 ) ) {
1336                 if ( ls != -1 ) {
1337                     sb.setCharAt( ls, '\n' );
1338                     start = ls + 1;
1339                     ls = -1;
1340                 }
1341                 else {
1342                     sb.insert( i, '\n' );
1343                     start = i + 1;
1344                 }
1345             }
1346             i++;
1347         }
1348         return sb.toString();
1349     }
1350
1351     /**
1352      * Helper method for calcColor methods.
1353      * 
1354      * @param smallercolor_component_x
1355      *            color component the smaller color
1356      * @param largercolor_component_x
1357      *            color component the larger color
1358      * @param x
1359      *            factor
1360      * @return an int representing a color component
1361      */
1362     final private static int calculateColorComponent( final double smallercolor_component_x,
1363                                                       final double largercolor_component_x,
1364                                                       final double x ) {
1365         return ( int ) ( smallercolor_component_x + ( ( x * ( largercolor_component_x - smallercolor_component_x ) ) / 255.0 ) );
1366     }
1367
1368     final public static MolecularSequence.TYPE guessMolecularSequenceType( final String mol_seq ) {
1369         if ( mol_seq.contains( "L" ) || mol_seq.contains( "I" ) || mol_seq.contains( "E" ) || mol_seq.contains( "H" )
1370                 || mol_seq.contains( "D" ) || mol_seq.contains( "Q" ) ) {
1371             return TYPE.AA;
1372         }
1373         else {
1374             if ( mol_seq.contains( "T" ) ) {
1375                 return TYPE.DNA;
1376             }
1377             else if ( mol_seq.contains( "U" ) ) {
1378                 return TYPE.RNA;
1379             }
1380         }
1381         return null;
1382     }
1383
1384     /**
1385      * Helper method for calcColor methods.
1386      * 
1387      * 
1388      * @param value
1389      *            the value
1390      * @param larger
1391      *            the largest value
1392      * @param smaller
1393      *            the smallest value
1394      * @return a normalized value between larger and smaller
1395      */
1396     final private static double calculateColorFactor( final double value, final double larger, final double smaller ) {
1397         return ( 255.0 * ( value - smaller ) ) / ( larger - smaller );
1398     }
1399
1400     final private static String[] splitString( final String str ) {
1401         final String regex = "[\\s;,]+";
1402         return str.split( regex );
1403     }
1404 }