(no commit message)
[jalview.git] / forester / java / src / org / forester / pccx / BasicExternalNodeBasedCoverageExtender.java
1 // $Id:
2 // cmzmasek Exp $
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.pccx;
28
29 import java.io.PrintStream;
30 import java.util.ArrayList;
31 import java.util.HashSet;
32 import java.util.List;
33 import java.util.Set;
34 import java.util.SortedMap;
35 import java.util.TreeMap;
36
37 import org.forester.phylogeny.Phylogeny;
38 import org.forester.phylogeny.PhylogenyNode;
39 import org.forester.phylogeny.iterators.PhylogenyNodeIterator;
40 import org.forester.util.ForesterUtil;
41
42 /*
43  * @author Christian M. Zmasek
44  */
45 public class BasicExternalNodeBasedCoverageExtender implements CoverageExtender {
46
47     private String find( final CoverageCalculationOptions options,
48                          final BranchCountingBasedScoringMethod scoring_method,
49                          final List<SortedMap<PhylogenyNode, Double>> external_node_scores_list,
50                          final List<SortedMap<PhylogenyNode, Double>> external_node_scores_list_temp,
51                          final List<Phylogeny> phylogenies,
52                          final Set<String> already_covered,
53                          final PrintStream out,
54                          final int i,
55                          final double normalization_factor ) {
56         final Phylogeny p = phylogenies.get( 0 );
57         String best_name = null;
58         double best_score = -Double.MAX_VALUE;
59         for( final PhylogenyNodeIterator iter = p.iteratorExternalForward(); iter.hasNext(); ) {
60             final String name = iter.next().getName();
61             if ( !already_covered.contains( name ) ) {
62                 final double score = BasicExternalNodeBasedCoverageExtender
63                         .calculateCoverage( phylogenies,
64                                             name,
65                                             options,
66                                             scoring_method,
67                                             external_node_scores_list_temp,
68                                             false );
69                 if ( score > best_score ) {
70                     best_score = score;
71                     best_name = name;
72                 }
73             }
74         }
75         BasicExternalNodeBasedCoverageExtender.calculateCoverage( phylogenies,
76                                                                   best_name,
77                                                                   options,
78                                                                   scoring_method,
79                                                                   external_node_scores_list_temp,
80                                                                   true );
81         if ( out != null ) {
82             out.println( i + "\t" + best_name + "\t" + ( best_score * normalization_factor ) );
83         }
84         return best_name;
85     }
86
87     /*
88      * (non-Javadoc)
89      *
90      * @see org.forester.tools.modeling.CoverageExtender#find(java.util.List,
91      *      java.util.List, int,
92      *      org.forester.tools.modeling.CoverageCalculationMethod,
93      *      org.forester.tools.modeling.CoverageCalculationOptions,
94      *      java.io.PrintStream)
95      */
96     @Override
97     public List<String> find( final List<Phylogeny> phylogenies,
98                               final List<String> already_covered,
99                               int number_names_to_find,
100                               final CoverageCalculationOptions options,
101                               final PrintStream out ) {
102         final ExternalNodeBasedCoverageMethodOptions my_options = ( ExternalNodeBasedCoverageMethodOptions ) options;
103         if ( ( my_options == null ) || ForesterUtil.isEmpty( my_options.getScoringMethod() ) ) {
104             throw new IllegalArgumentException( "options for external node based coverage method appear to not have been set" );
105         }
106         BranchCountingBasedScoringMethod scoring_method;
107         try {
108             scoring_method = ( BranchCountingBasedScoringMethod ) ( Class.forName( my_options.getScoringMethod() ) )
109                     .newInstance();
110         }
111         catch ( final Exception e ) {
112             throw new IllegalArgumentException( "could not create scoring method class \""
113                     + my_options.getScoringMethod() + "\"" );
114         }
115         final List<String> best_names = new ArrayList<String>();
116         final Set<String> my_already_covered = new HashSet<String>();
117         final List<SortedMap<PhylogenyNode, Double>> external_node_scores_list = new ArrayList<SortedMap<PhylogenyNode, Double>>();
118         for( int i = 0; i < phylogenies.size(); ++i ) {
119             external_node_scores_list.add( ModelingUtils.setUpExternalCoverageHashMap( phylogenies.get( i ) ) );
120         }
121         if ( already_covered != null ) {
122             for( final String name : already_covered ) {
123                 my_already_covered.add( name );
124                 BasicExternalNodeBasedCoverageExtender.calculateCoverage( phylogenies,
125                                                                           name,
126                                                                           options,
127                                                                           scoring_method,
128                                                                           external_node_scores_list,
129                                                                           true );
130             }
131         }
132         if ( number_names_to_find < 1 ) {
133             number_names_to_find = phylogenies.get( 0 ).getNumberOfExternalNodes() - my_already_covered.size();
134         }
135         final double normalization_factor = scoring_method.getNormalizationFactor( phylogenies.get( 0 ) );
136         for( int i = 0; i < number_names_to_find; ++i ) {
137             final String name = find( my_options,
138                                       scoring_method,
139                                       external_node_scores_list,
140                                       external_node_scores_list,
141                                       phylogenies,
142                                       my_already_covered,
143                                       out,
144                                       i,
145                                       normalization_factor );
146             my_already_covered.add( name );
147             best_names.add( name );
148         }
149         return best_names;
150     }
151
152     private static double calculateCoverage( final List<Phylogeny> phylogenies,
153                                              final String name,
154                                              final CoverageCalculationOptions options,
155                                              final BranchCountingBasedScoringMethod scoring_method,
156                                              final List<SortedMap<PhylogenyNode, Double>> external_node_scores_list,
157                                              final boolean update_external_node_scores_list ) {
158         int i = 0;
159         double score_sum = 0.0;
160         for( final Object element : phylogenies ) {
161             SortedMap<PhylogenyNode, Double> external_node_scores;
162             if ( update_external_node_scores_list ) {
163                 external_node_scores = external_node_scores_list.get( i++ );
164             }
165             else {
166                 external_node_scores = new TreeMap<PhylogenyNode, Double>( external_node_scores_list.get( i++ ) );
167             }
168             final Phylogeny phylogeny = ( Phylogeny ) element;
169             scoring_method.calculateScoreForExternalNode( external_node_scores,
170                                                           phylogeny,
171                                                           phylogeny.getNode( name ),
172                                                           options );
173             for( final Object element2 : external_node_scores.values() ) {
174                 score_sum += ( ( Double ) element2 ).doubleValue();
175             }
176         }
177         return score_sum / i;
178     }
179 }