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