moved to: https://sites.google.com/site/cmzmasek/home/software/forester
[jalview.git] / forester / java / src / org / forester / tools / ConfidenceAssessor.java
1 // $Id:
2 //
3 // FORESTER -- software libraries and applications
4 // for evolutionary biology research and applications.
5 //
6 // Copyright (C) 2008-2009 Christian M. Zmasek
7 // Copyright (C) 2008-2009 Burnham Institute for Medical Research
8 // All rights reserved
9 //
10 // This library is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU Lesser General Public
12 // License as published by the Free Software Foundation; either
13 // version 2.1 of the License, or (at your option) any later version.
14 //
15 // This library is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 // Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public
21 // License along with this library; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 //
24 // Contact: phylosoft @ gmail . com
25 // WWW: https://sites.google.com/site/cmzmasek/home/software/forester
26
27 package org.forester.tools;
28
29 import java.util.HashMap;
30 import java.util.HashSet;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.Set;
34
35 import org.forester.phylogeny.Phylogeny;
36 import org.forester.phylogeny.PhylogenyNode;
37 import org.forester.phylogeny.data.Confidence;
38 import org.forester.phylogeny.iterators.PhylogenyNodeIterator;
39 import org.forester.util.ForesterUtil;
40
41 public final class ConfidenceAssessor {
42
43     private ConfidenceAssessor() {
44         // Hidden constructor.
45     }
46
47     private final static void addExternalNodesToMap( final Map<PhylogenyNode, Set<PhylogenyNode>> node_to_ext_nodes_map,
48                                                      final PhylogenyNode node ) {
49         final Set<PhylogenyNode> ex_descs = new HashSet<PhylogenyNode>();
50         for( final PhylogenyNode n : node.getAllExternalDescendants() ) {
51             if ( ex_descs.contains( n ) ) {
52                 throw new IllegalArgumentException( "node [" + n.toString() + "] of target is not unique" );
53             }
54             ex_descs.add( n );
55         }
56         node_to_ext_nodes_map.put( node, ex_descs );
57     }
58
59     private final static void checkPreconditions( final String confidence_type,
60                                                   final Phylogeny[] evaluators,
61                                                   final Phylogeny target,
62                                                   final double value,
63                                                   final int first,
64                                                   final int last ) {
65         if ( ( first < 0 ) || ( last < 0 ) ) {
66             throw new IllegalArgumentException( "attempt to set first or last evaluator topology to use to a number less than zero" );
67         }
68         if ( evaluators.length < 1 ) {
69             throw new IllegalArgumentException( "need at least one evaluator topology" );
70         }
71         if ( ForesterUtil.isEmpty( confidence_type ) ) {
72             throw new IllegalArgumentException( "attempt to use empty confidence type" );
73         }
74         if ( value <= 0 ) {
75             throw new IllegalArgumentException( "attempt to use zero or negative \'count value\'" );
76         }
77         if ( ( first != 0 ) || ( last != 0 ) ) {
78             if ( ( last >= evaluators.length ) || ( last <= first ) ) {
79                 throw new IllegalArgumentException( "illegal value for last evaluator topology to use" );
80             }
81         }
82         final Set<PhylogenyNode> nodes = new HashSet<PhylogenyNode>();
83         for( final PhylogenyNodeIterator it = target.iteratorPostorder(); it.hasNext(); ) {
84             final PhylogenyNode node = it.next();
85             if ( nodes.contains( node ) ) {
86                 throw new IllegalArgumentException( "node [" + node + "] in target is not unique" );
87             }
88             nodes.add( node );
89             final List<Confidence> confidences = node.getBranchData().getConfidences();
90             for( final Confidence confidence : confidences ) {
91                 if ( confidence.getType().equals( confidence_type ) ) {
92                     throw new IllegalArgumentException( "confidence [" + confidence_type
93                             + "] is already present in target" );
94                 }
95             }
96         }
97     }
98
99     public final static void evaluate( final String confidence_type,
100                                        final Phylogeny[] evaluators,
101                                        final Phylogeny target,
102                                        final boolean strict,
103                                        final double value ) {
104         evaluate( confidence_type, evaluators, target, strict, value, 0, 0 );
105     }
106
107     public final static void evaluate( final String confidence_type,
108                                        final Phylogeny[] evaluators,
109                                        final Phylogeny target,
110                                        final boolean strict,
111                                        final double value,
112                                        final int first,
113                                        final int last ) {
114         try {
115             checkPreconditions( confidence_type, evaluators, target, value, first, last );
116         }
117         catch ( final IllegalArgumentException e ) {
118             throw e;
119         }
120         boolean all = true;
121         if ( ( first != 0 ) || ( last != 0 ) ) {
122             all = false;
123         }
124         int counter = 0;
125         final Map<PhylogenyNode, Set<PhylogenyNode>> node_to_ext_nodes_map = new HashMap<PhylogenyNode, Set<PhylogenyNode>>();
126         for( final Phylogeny evaluator : evaluators ) {
127             if ( all || ( ( counter >= first ) && ( counter <= last ) ) ) {
128                 if ( strict ) {
129                     if ( evaluator.getNumberOfExternalNodes() != target.getNumberOfExternalNodes() ) {
130                         throw new IllegalArgumentException( "evaluator #" + counter
131                                 + " does not have the same number of external nodes ["
132                                 + evaluator.getNumberOfExternalNodes() + "] than the corresponding target ["
133                                 + target.getNumberOfExternalNodes() + "]" );
134                     }
135                 }
136                 final TreeSplitMatrix s = new TreeSplitMatrix( evaluator, strict, target );
137                 for( final PhylogenyNodeIterator it = target.iteratorPostorder(); it.hasNext(); ) {
138                     final PhylogenyNode node = it.next();
139                     if ( !node.isExternal() && !node.isRoot() ) {
140                         if ( node.getParent().isRoot()
141                                 && ( target.getRoot().getNumberOfDescendants() == 2 )
142                                 && ( target.getRoot().getChildNode1().isExternal() || target.getRoot().getChildNode2()
143                                         .isExternal() ) ) {
144                             continue;
145                         }
146                         if ( !node_to_ext_nodes_map.containsKey( node ) ) {
147                             addExternalNodesToMap( node_to_ext_nodes_map, node );
148                         }
149                         final Set<PhylogenyNode> ex_descs = node_to_ext_nodes_map.get( node );
150                         final Confidence c = ConfidenceAssessor.obtainConfidence( node, confidence_type );
151                         if ( s.match( ex_descs ) ) {
152                             c.setValue( c.getValue() + value );
153                         }
154                     }
155                 }
156             }
157             ++counter;
158         }
159     }
160
161     private final static Confidence obtainConfidence( final PhylogenyNode n, final String confidence_type ) {
162         final List<Confidence> confidences = n.getBranchData().getConfidences();
163         Confidence match = null;
164         for( final Confidence confidence : confidences ) {
165             if ( confidence.getType().equals( confidence_type ) ) {
166                 if ( match != null ) {
167                     throw new IllegalArgumentException( "confidence [" + confidence_type + "] is not unique" );
168                 }
169                 match = confidence;
170             }
171         }
172         if ( match == null ) {
173             match = new Confidence( 0, confidence_type );
174             confidences.add( match );
175         }
176         return match;
177     }
178 }