5b5537ca7bbbdfc4444d1eb2f631fe1b9a071dbb
[jalview.git] / forester / java / src / org / forester / archaeopteryx / TreePanelUtil.java
1
2 package org.forester.archaeopteryx;
3
4 import java.awt.Color;
5 import java.awt.Component;
6 import java.io.UnsupportedEncodingException;
7 import java.net.URLEncoder;
8 import java.util.ArrayList;
9 import java.util.HashMap;
10 import java.util.HashSet;
11 import java.util.List;
12 import java.util.Map;
13 import java.util.Map.Entry;
14 import java.util.Set;
15 import java.util.SortedMap;
16 import java.util.SortedSet;
17 import java.util.TreeMap;
18
19 import javax.swing.JOptionPane;
20
21 import org.forester.analysis.TaxonomyDataManager;
22 import org.forester.phylogeny.Phylogeny;
23 import org.forester.phylogeny.PhylogenyMethods;
24 import org.forester.phylogeny.PhylogenyNode;
25 import org.forester.phylogeny.data.Accession;
26 import org.forester.phylogeny.data.Annotation;
27 import org.forester.phylogeny.data.BranchColor;
28 import org.forester.phylogeny.data.NodeData.NODE_DATA;
29 import org.forester.phylogeny.data.Sequence;
30 import org.forester.phylogeny.data.Taxonomy;
31 import org.forester.phylogeny.iterators.PhylogenyNodeIterator;
32 import org.forester.phylogeny.iterators.PreorderTreeIterator;
33 import org.forester.util.ForesterConstants;
34 import org.forester.util.ForesterUtil;
35 import org.forester.util.SequenceAccessionTools;
36 import org.forester.ws.seqdb.UniProtTaxonomy;
37
38 public class TreePanelUtil {
39
40     public final static String createUriForSeqWeb( final PhylogenyNode node,
41                                                    final Configuration conf,
42                                                    final TreePanel tp ) {
43         String uri_str = null;
44         final String upkb = SequenceAccessionTools.obtainUniProtAccessorFromDataFields( node );
45         if ( !ForesterUtil.isEmpty( upkb ) ) {
46             try {
47                 uri_str = ForesterUtil.UNIPROT_KB + URLEncoder.encode( upkb, ForesterConstants.UTF8 );
48             }
49             catch ( final UnsupportedEncodingException e ) {
50                 AptxUtil.showErrorMessage( tp, e.toString() );
51                 e.printStackTrace();
52             }
53         }
54         if ( ForesterUtil.isEmpty( uri_str ) ) {
55             final String v = SequenceAccessionTools.obtainGenbankAccessorFromDataFields( node );
56             if ( !ForesterUtil.isEmpty( v ) ) {
57                 try {
58                     if ( SequenceAccessionTools.isProteinDbQuery( v ) ) {
59                         uri_str = ForesterUtil.NCBI_PROTEIN + URLEncoder.encode( v, ForesterConstants.UTF8 );
60                     }
61                     else {
62                         uri_str = ForesterUtil.NCBI_NUCCORE + URLEncoder.encode( v, ForesterConstants.UTF8 );
63                     }
64                 }
65                 catch ( final UnsupportedEncodingException e ) {
66                     AptxUtil.showErrorMessage( tp, e.toString() );
67                     e.printStackTrace();
68                 }
69             }
70         }
71         if ( ForesterUtil.isEmpty( uri_str ) ) {
72             final String v = SequenceAccessionTools.obtainRefSeqAccessorFromDataFields( node );
73             if ( !ForesterUtil.isEmpty( v ) ) {
74                 try {
75                     if ( SequenceAccessionTools.isProteinDbQuery( v ) ) {
76                         uri_str = ForesterUtil.NCBI_PROTEIN + URLEncoder.encode( v, ForesterConstants.UTF8 );
77                     }
78                     else {
79                         uri_str = ForesterUtil.NCBI_NUCCORE + URLEncoder.encode( v, ForesterConstants.UTF8 );
80                     }
81                 }
82                 catch ( final UnsupportedEncodingException e ) {
83                     AptxUtil.showErrorMessage( tp, e.toString() );
84                     e.printStackTrace();
85                 }
86             }
87         }
88         if ( ForesterUtil.isEmpty( uri_str ) ) {
89             final String v = SequenceAccessionTools.obtainGiNumberFromDataFields( node );
90             if ( !ForesterUtil.isEmpty( v ) ) {
91                 try {
92                     uri_str = ForesterUtil.NCBI_GI + URLEncoder.encode( v, ForesterConstants.UTF8 );
93                 }
94                 catch ( final UnsupportedEncodingException e ) {
95                     AptxUtil.showErrorMessage( tp, e.toString() );
96                     e.printStackTrace();
97                 }
98             }
99         }
100         return uri_str;
101     }
102
103     public static List<String> createUrisForPdbWeb( final PhylogenyNode node,
104                                                     final List<Accession> pdb_accs,
105                                                     final Configuration configuration,
106                                                     final TreePanel treePanel ) {
107         final List<String> uris = new ArrayList<String>();
108         if ( !ForesterUtil.isEmpty( pdb_accs ) ) {
109             for( final Accession pdb_acc : pdb_accs ) {
110                 if ( !ForesterUtil.isEmpty( pdb_acc.getValue() ) ) {
111                     uris.add( ForesterUtil.PDB + pdb_acc.getValue() );
112                 }
113             }
114         }
115         return uris;
116     }
117
118     /**
119      * Returns the set of distinct taxonomies of
120      * all external nodes of node.
121      * If at least one the external nodes has no taxonomy,
122      * null is returned.
123      * 
124      */
125     public static Set<Taxonomy> obtainDistinctTaxonomies( final PhylogenyNode node ) {
126         final List<PhylogenyNode> descs = node.getAllExternalDescendants();
127         final Set<Taxonomy> tax_set = new HashSet<Taxonomy>();
128         for( final PhylogenyNode n : descs ) {
129             if ( !n.getNodeData().isHasTaxonomy() || n.getNodeData().getTaxonomy().isEmpty() ) {
130                 return null;
131             }
132             tax_set.add( n.getNodeData().getTaxonomy() );
133         }
134         return tax_set;
135     }
136
137     public final static void showExtDescNodeDataUserSelectedHelper( final ControlPanel cp,
138                                                                     final PhylogenyNode node,
139                                                                     final List<String> data ) {
140         final StringBuilder sb = new StringBuilder();
141         if ( cp.isShowNodeNames() && !ForesterUtil.isEmpty( node.getName() ) ) {
142             TreePanelUtil.showExtDescNodeDataUserSelectedHelperHelper( node.getName(), sb );
143         }
144         if ( cp.isShowSeqNames() && node.getNodeData().isHasSequence()
145                 && !ForesterUtil.isEmpty( node.getNodeData().getSequence().getName() ) ) {
146             TreePanelUtil.showExtDescNodeDataUserSelectedHelperHelper( node.getNodeData().getSequence().getName(), sb );
147         }
148         if ( cp.isShowSeqSymbols() && node.getNodeData().isHasSequence()
149                 && !ForesterUtil.isEmpty( node.getNodeData().getSequence().getSymbol() ) ) {
150             TreePanelUtil
151                     .showExtDescNodeDataUserSelectedHelperHelper( node.getNodeData().getSequence().getSymbol(), sb );
152         }
153         if ( cp.isShowGeneNames() && node.getNodeData().isHasSequence()
154                 && !ForesterUtil.isEmpty( node.getNodeData().getSequence().getGeneName() ) ) {
155             TreePanelUtil.showExtDescNodeDataUserSelectedHelperHelper( node.getNodeData().getSequence().getGeneName(),
156                                                                        sb );
157         }
158         if ( cp.isShowSequenceAcc() && node.getNodeData().isHasSequence()
159                 && ( node.getNodeData().getSequence().getAccession() != null )
160                 && !ForesterUtil.isEmpty( node.getNodeData().getSequence().getAccession().toString() ) ) {
161             TreePanelUtil.showExtDescNodeDataUserSelectedHelperHelper( node.getNodeData().getSequence().getAccession()
162                     .toString(), sb );
163         }
164         if ( cp.isShowTaxonomyCode() && node.getNodeData().isHasTaxonomy()
165                 && !ForesterUtil.isEmpty( node.getNodeData().getTaxonomy().getTaxonomyCode() ) ) {
166             TreePanelUtil.showExtDescNodeDataUserSelectedHelperHelper( node.getNodeData().getTaxonomy()
167                     .getTaxonomyCode(), sb );
168         }
169         if ( cp.isShowTaxonomyScientificNames() && node.getNodeData().isHasTaxonomy()
170                 && !ForesterUtil.isEmpty( node.getNodeData().getTaxonomy().getScientificName() ) ) {
171             TreePanelUtil.showExtDescNodeDataUserSelectedHelperHelper( node.getNodeData().getTaxonomy()
172                     .getScientificName(), sb );
173         }
174         if ( cp.isShowTaxonomyCommonNames() && node.getNodeData().isHasTaxonomy()
175                 && !ForesterUtil.isEmpty( node.getNodeData().getTaxonomy().getCommonName() ) ) {
176             TreePanelUtil
177                     .showExtDescNodeDataUserSelectedHelperHelper( node.getNodeData().getTaxonomy().getCommonName(), sb );
178         }
179         if ( ( cp.isShowSeqNames() || cp.isShowSeqSymbols() || cp.isShowSequenceAcc() )
180                 && node.getNodeData().isHasSequence()
181                 && !ForesterUtil.isEmpty( node.getNodeData().getSequence().getMolecularSequence() ) ) {
182             TreePanelUtil.showExtDescNodeDataUserSelectedHelperHelper( node.getNodeData().getSequence()
183                     .getMolecularSequence(), sb );
184         }
185         final String s = sb.toString().trim();
186         if ( !ForesterUtil.isEmpty( s ) ) {
187             data.add( s );
188         }
189     }
190
191     public final static void showExtDescNodeDataUserSelectedHelperHelper( final String s, final StringBuilder sb ) {
192         if ( sb.length() > 0 ) {
193             sb.append( "\t" );
194         }
195         sb.append( s );
196     }
197
198     final public static void showInformationMessage( final Component parent, final String title, final String msg ) {
199         JOptionPane.showMessageDialog( parent, msg, title, JOptionPane.INFORMATION_MESSAGE );
200     }
201
202     final static Color calculateColorFromString( final String str, final boolean is_taxonomy ) {
203         final String my_str = str.toUpperCase();
204         char first = my_str.charAt( 0 );
205         char second = ' ';
206         char third = ' ';
207         if ( my_str.length() > 1 ) {
208             if ( is_taxonomy ) {
209                 second = my_str.charAt( 1 );
210             }
211             else {
212                 second = my_str.charAt( my_str.length() - 1 );
213             }
214             if ( is_taxonomy ) {
215                 if ( my_str.length() > 2 ) {
216                     if ( my_str.indexOf( " " ) > 0 ) {
217                         third = my_str.charAt( my_str.indexOf( " " ) + 1 );
218                     }
219                     else {
220                         third = my_str.charAt( 2 );
221                     }
222                 }
223             }
224             else if ( my_str.length() > 2 ) {
225                 third = my_str.charAt( ( my_str.length() - 1 ) / 2 );
226             }
227         }
228         first = TreePanelUtil.normalizeCharForRGB( first );
229         second = TreePanelUtil.normalizeCharForRGB( second );
230         third = TreePanelUtil.normalizeCharForRGB( third );
231         if ( ( first > 235 ) && ( second > 235 ) && ( third > 235 ) ) {
232             first = 0;
233         }
234         else if ( ( first < 60 ) && ( second < 60 ) && ( third < 60 ) ) {
235             second = 255;
236         }
237         return new Color( first, second, third );
238     }
239
240     final static void collapseSpeciesSpecificSubtrees( final Phylogeny phy ) {
241         boolean inferred = false;
242         for( final PhylogenyNodeIterator it = phy.iteratorPreorder(); it.hasNext(); ) {
243             final PhylogenyNode n = it.next();
244             if ( !n.isExternal() && !n.isCollapse() && ( n.getNumberOfDescendants() > 1 ) ) {
245                 final Set<Taxonomy> taxs = TreePanelUtil.obtainDistinctTaxonomies( n );
246                 if ( ( taxs != null ) && ( taxs.size() == 1 ) ) {
247                     TreePanelUtil.collapseSubtree( n, true );
248                     if ( !n.getNodeData().isHasTaxonomy() ) {
249                         n.getNodeData().setTaxonomy( ( Taxonomy ) n.getAllExternalDescendants().get( 0 ).getNodeData()
250                                 .getTaxonomy().copy() );
251                     }
252                     inferred = true;
253                 }
254                 else {
255                     n.setCollapse( false );
256                 }
257             }
258         }
259         if ( inferred ) {
260             phy.setRerootable( false );
261         }
262     }
263
264     final static void collapseSubtree( final PhylogenyNode node, final boolean collapse ) {
265         node.setCollapse( collapse );
266         if ( node.isExternal() ) {
267             return;
268         }
269         final PhylogenyNodeIterator it = new PreorderTreeIterator( node );
270         while ( it.hasNext() ) {
271             it.next().setCollapse( collapse );
272         }
273     }
274
275     static void colorizeSubtree( final PhylogenyNode node, final BranchColor c ) {
276         node.getBranchData().setBranchColor( c );
277         final List<PhylogenyNode> descs = PhylogenyMethods.getAllDescendants( node );
278         for( final PhylogenyNode desc : descs ) {
279             desc.getBranchData().setBranchColor( c );
280         }
281     }
282
283     final static void colorPhylogenyAccordingToConfidenceValues( final Phylogeny tree, final TreePanel tree_panel ) {
284         double max_conf = 0.0;
285         for( final PhylogenyNodeIterator it = tree.iteratorPreorder(); it.hasNext(); ) {
286             final PhylogenyNode n = it.next();
287             n.getBranchData().setBranchColor( null );
288             if ( n.getBranchData().isHasConfidences() ) {
289                 final double conf = PhylogenyMethods.getConfidenceValue( n );
290                 if ( conf > max_conf ) {
291                     max_conf = conf;
292                 }
293             }
294         }
295         if ( max_conf > 0.0 ) {
296             final Color bg = tree_panel.getTreeColorSet().getBackgroundColor();
297             final Color br = tree_panel.getTreeColorSet().getBranchColor();
298             for( final PhylogenyNodeIterator it = tree.iteratorPreorder(); it.hasNext(); ) {
299                 final PhylogenyNode n = it.next();
300                 if ( n.getBranchData().isHasConfidences() ) {
301                     final double conf = PhylogenyMethods.getConfidenceValue( n );
302                     final BranchColor c = new BranchColor( ForesterUtil.calcColor( conf, 0.0, max_conf, bg, br ) );
303                     TreePanelUtil.colorizeSubtree( n, c );
304                 }
305             }
306         }
307     }
308
309     final static void colorPhylogenyAccordingToExternalTaxonomy( final Phylogeny tree, final TreePanel tree_panel ) {
310         for( final PhylogenyNodeIterator it = tree.iteratorPreorder(); it.hasNext(); ) {
311             it.next().getBranchData().setBranchColor( null );
312         }
313         for( final PhylogenyNodeIterator it = tree.iteratorPreorder(); it.hasNext(); ) {
314             final PhylogenyNode n = it.next();
315             if ( !n.getBranchData().isHasBranchColor() ) {
316                 final Taxonomy tax = PhylogenyMethods.getExternalDescendantsTaxonomy( n );
317                 if ( tax != null ) {
318                     n.getBranchData().setBranchColor( new BranchColor( tree_panel.calculateTaxonomyBasedColor( tax ) ) );
319                     final List<PhylogenyNode> descs = PhylogenyMethods.getAllDescendants( n );
320                     for( final PhylogenyNode desc : descs ) {
321                         desc.getBranchData()
322                                 .setBranchColor( new BranchColor( tree_panel.calculateTaxonomyBasedColor( tax ) ) );
323                     }
324                 }
325             }
326         }
327     }
328
329     final static int colorPhylogenyAccordingToRanks( final Phylogeny tree, final String rank, final TreePanel tree_panel ) {
330         final Map<String, Color> true_lineage_to_color_map = new HashMap<String, Color>();
331         int colorizations = 0;
332         for( final PhylogenyNodeIterator it = tree.iteratorPostorder(); it.hasNext(); ) {
333             final PhylogenyNode n = it.next();
334             if ( n.getNodeData().isHasTaxonomy()
335                     && ( !ForesterUtil.isEmpty( n.getNodeData().getTaxonomy().getScientificName() )
336                             || !ForesterUtil.isEmpty( n.getNodeData().getTaxonomy().getCommonName() ) || !ForesterUtil
337                             .isEmpty( n.getNodeData().getTaxonomy().getTaxonomyCode() ) ) ) {
338                 if ( !ForesterUtil.isEmpty( n.getNodeData().getTaxonomy().getRank() )
339                         && n.getNodeData().getTaxonomy().getRank().equalsIgnoreCase( rank ) ) {
340                     final BranchColor c = new BranchColor( tree_panel.calculateTaxonomyBasedColor( n.getNodeData()
341                             .getTaxonomy() ) );
342                     TreePanelUtil.colorizeSubtree( n, c );
343                     ++colorizations;
344                     if ( !ForesterUtil.isEmpty( n.getNodeData().getTaxonomy().getScientificName() ) ) {
345                         true_lineage_to_color_map.put( n.getNodeData().getTaxonomy().getScientificName(), c.getValue() );
346                     }
347                 }
348             }
349         }
350         for( final PhylogenyNodeIterator it = tree.iteratorPostorder(); it.hasNext(); ) {
351             final PhylogenyNode node = it.next();
352             if ( ( node.getBranchData().getBranchColor() == null ) && node.getNodeData().isHasTaxonomy()
353                     && !ForesterUtil.isEmpty( node.getNodeData().getTaxonomy().getLineage() ) ) {
354                 boolean success = false;
355                 if ( !true_lineage_to_color_map.isEmpty() ) {
356                     for( final String lin : node.getNodeData().getTaxonomy().getLineage() ) {
357                         if ( true_lineage_to_color_map.containsKey( lin ) ) {
358                             TreePanelUtil
359                                     .colorizeSubtree( node, new BranchColor( true_lineage_to_color_map.get( lin ) ) );
360                             ++colorizations;
361                             success = true;
362                             break;
363                         }
364                     }
365                 }
366                 if ( !success ) {
367                     final Map<String, String> lineage_to_rank_map = MainPanel.getLineageToRankMap();
368                     for( final String lin : node.getNodeData().getTaxonomy().getLineage() ) {
369                         final Taxonomy temp_tax = new Taxonomy();
370                         temp_tax.setScientificName( lin );
371                         if ( lineage_to_rank_map.containsKey( lin )
372                                 && !ForesterUtil.isEmpty( lineage_to_rank_map.get( lin ) )
373                                 && lineage_to_rank_map.get( lin ).equalsIgnoreCase( rank ) ) {
374                             final BranchColor c = new BranchColor( tree_panel.calculateTaxonomyBasedColor( temp_tax ) );
375                             TreePanelUtil.colorizeSubtree( node, c );
376                             ++colorizations;
377                             true_lineage_to_color_map.put( lin, c.getValue() );
378                             break;
379                         }
380                         else {
381                             UniProtTaxonomy up = null;
382                             try {
383                                 up = TaxonomyDataManager.obtainUniProtTaxonomy( temp_tax, null, null );
384                             }
385                             catch ( final Exception e ) {
386                                 e.printStackTrace();
387                             }
388                             if ( ( up != null ) && !ForesterUtil.isEmpty( up.getRank() ) ) {
389                                 lineage_to_rank_map.put( lin, up.getRank() );
390                                 if ( up.getRank().equalsIgnoreCase( rank ) ) {
391                                     final BranchColor c = new BranchColor( tree_panel.calculateTaxonomyBasedColor( temp_tax ) );
392                                     TreePanelUtil.colorizeSubtree( node, c );
393                                     ++colorizations;
394                                     true_lineage_to_color_map.put( lin, c.getValue() );
395                                     break;
396                                 }
397                             }
398                         }
399                     }
400                 }
401             }
402         }
403         return colorizations;
404     }
405
406     final static String createAnnotationString( final SortedSet<Annotation> annotations, final boolean show_ref_sources ) {
407         final SortedMap<String, List<Annotation>> m = new TreeMap<String, List<Annotation>>();
408         for( final Annotation an : annotations ) {
409             final String ref_source = ForesterUtil.isEmpty( an.getRefSource() ) ? "?" : an.getRefSource();
410             if ( !m.containsKey( ref_source ) ) {
411                 m.put( ref_source, new ArrayList<Annotation>() );
412             }
413             m.get( ref_source ).add( an );
414         }
415         final StringBuilder sb = new StringBuilder();
416         for( final Entry<String, List<Annotation>> e : m.entrySet() ) {
417             final String ref_source = e.getKey();
418             final List<Annotation> ans = e.getValue();
419             if ( m.size() > 1 ) {
420                 sb.append( "[" );
421             }
422             if ( show_ref_sources && !ref_source.equals( "?" ) ) {
423                 sb.append( ref_source );
424                 sb.append( ": " );
425             }
426             for( int i = 0; i < ans.size(); ++i ) {
427                 final Annotation an = ans.get( i );
428                 if ( !ForesterUtil.isEmpty( an.getRefValue() ) ) {
429                     sb.append( an.getRefValue() );
430                     sb.append( " " );
431                 }
432                 if ( !ForesterUtil.isEmpty( an.getDesc() ) ) {
433                     sb.append( an.getDesc() );
434                 }
435                 if ( sb.charAt( sb.length() - 1 ) == ' ' ) {
436                     sb.deleteCharAt( sb.length() - 1 );
437                 }
438                 if ( i < ans.size() - 1 ) {
439                     sb.append( ", " );
440                 }
441             }
442             if ( m.size() > 1 ) {
443                 sb.append( "] " );
444             }
445         }
446         return sb.toString();
447     }
448
449     final static String getPartAfterColon( final String s ) {
450         final int i = s.indexOf( ':' );
451         if ( ( i < 1 ) || ( i == ( s.length() - 1 ) ) ) {
452             return s;
453         }
454         return s.substring( i + 1, s.length() );
455     }
456
457     final static boolean isHasAssignedEvent( final PhylogenyNode node ) {
458         if ( !node.getNodeData().isHasEvent() ) {
459             return false;
460         }
461         if ( ( node.getNodeData().getEvent() ).isUnassigned() ) {
462             return false;
463         }
464         return true;
465     }
466
467     final static boolean isSequenceEmpty( final Sequence seq ) {
468         return ( seq.getAccession() == null ) && ForesterUtil.isEmpty( seq.getName() )
469                 && ForesterUtil.isEmpty( seq.getGeneName() ) && ForesterUtil.isEmpty( seq.getSymbol() );
470     }
471
472     final static boolean isTaxonomyEmpty( final Taxonomy tax ) {
473         return ( ( tax.getIdentifier() == null ) && ForesterUtil.isEmpty( tax.getTaxonomyCode() )
474                 && ForesterUtil.isEmpty( tax.getCommonName() ) && ForesterUtil.isEmpty( tax.getScientificName() ) && tax
475                 .getSynonyms().isEmpty() );
476     }
477
478     static int makeSB( final List<String> data, final Options optz, final StringBuilder sb ) {
479         final SortedMap<String, Integer> map = new TreeMap<String, Integer>();
480         if ( ( optz.getExtDescNodeDataToReturn() != NODE_DATA.SEQUENCE_MOL_SEQ )
481                 && ( optz.getExtDescNodeDataToReturn() != NODE_DATA.SEQUENCE_MOL_SEQ_FASTA ) ) {
482             for( final String d : data ) {
483                 if ( !ForesterUtil.isEmpty( d ) ) {
484                     if ( map.containsKey( d ) ) {
485                         map.put( d, map.get( d ) + 1 );
486                     }
487                     else {
488                         map.put( d, 1 );
489                     }
490                 }
491             }
492         }
493         int size = 0;
494         if ( ( optz.getExtDescNodeDataToReturn() != NODE_DATA.SEQUENCE_MOL_SEQ )
495                 && ( optz.getExtDescNodeDataToReturn() != NODE_DATA.SEQUENCE_MOL_SEQ_FASTA ) ) {
496             for( final Entry<String, Integer> e : map.entrySet() ) {
497                 final String v = e.getKey();
498                 final Object c = e.getValue();
499                 sb.append( v );
500                 sb.append( "\t" );
501                 sb.append( c );
502                 sb.append( ForesterUtil.LINE_SEPARATOR );
503             }
504             size = map.size();
505         }
506         else {
507             for( final String d : data ) {
508                 if ( !ForesterUtil.isEmpty( d ) ) {
509                     sb.append( d );
510                     sb.append( ForesterUtil.LINE_SEPARATOR );
511                 }
512             }
513             size = data.size();
514         }
515         return size;
516     }
517
518     final static char normalizeCharForRGB( char c ) {
519         c -= 65;
520         c *= 10.2;
521         c = c > 255 ? 255 : c;
522         c = c < 0 ? 0 : c;
523         return c;
524     }
525
526     final static String pdbAccToString( final List<Accession> accs, final int i ) {
527         if ( ForesterUtil.isEmpty( accs.get( i ).getComment() ) ) {
528             return accs.get( i ).getValue();
529         }
530         return accs.get( i ).getValue() + " (" + accs.get( i ).getComment().toLowerCase() + ")";
531     }
532
533     final static Phylogeny subTree( final PhylogenyNode new_root, final Phylogeny source_phy ) {
534         final Phylogeny new_phy = new Phylogeny();
535         new_phy.setRooted( true );
536         new_phy.setName( source_phy.getName() );
537         new_phy.setDescription( source_phy.getDescription() );
538         new_phy.setType( source_phy.getType() );
539         new_phy.setDistanceUnit( source_phy.getDistanceUnit() );
540         new_phy.setConfidence( source_phy.getConfidence() );
541         new_phy.setIdentifier( source_phy.getIdentifier() );
542         new_phy.setRoot( new_root.copyNodeDataShallow() );
543         int i = 0;
544         for( final PhylogenyNode n : new_root.getDescendants() ) {
545             new_phy.getRoot().setChildNode( i++, n );
546         }
547         return new_phy;
548     }
549 }