9172696eaf9acf4fee3ab7973a56c9197918d28f
[jalview.git] / forester / java / src / org / forester / msa / MsaCompactor.java
1
2 package org.forester.msa;
3
4 import java.io.IOException;
5 import java.util.ArrayList;
6 import java.util.Arrays;
7 import java.util.Comparator;
8 import java.util.List;
9 import java.util.SortedSet;
10 import java.util.TreeSet;
11
12 import org.forester.sequence.Sequence;
13 import org.forester.util.BasicDescriptiveStatistics;
14 import org.forester.util.DescriptiveStatistics;
15 import org.forester.util.ForesterUtil;
16
17 public class MsaCompactor {
18
19     private static final boolean    VERBOSE = true;
20     private Msa                     _msa;
21     private final SortedSet<String> _removed_seq_ids;
22
23     private MsaCompactor( final Msa msa ) {
24         _msa = msa;
25         _removed_seq_ids = new TreeSet<String>();
26     }
27
28     final public SortedSet<String> getRemovedSeqIds() {
29         return _removed_seq_ids;
30     }
31
32     final public Msa getMsa() {
33         return _msa;
34     }
35
36     public final static MsaCompactor removeWorstOffenders( final Msa msa,
37                                                            final int worst_offenders_to_remove,
38                                                            final boolean realign ) throws IOException,
39             InterruptedException {
40         final MsaCompactor mc = new MsaCompactor( msa );
41         mc.removeWorstOffenders( worst_offenders_to_remove, 1, realign );
42         return mc;
43     }
44
45     public final static MsaCompactor reduceGapAverage( final Msa msa,
46                                                        final double max_gap_average,
47                                                        final int step,
48                                                        final boolean realign ) throws IOException, InterruptedException {
49         final MsaCompactor mc = new MsaCompactor( msa );
50         mc.removeViaGapAverage( max_gap_average, step, realign );
51         return mc;
52     }
53
54     public final static MsaCompactor reduceLength( final Msa msa,
55                                                    final int length,
56                                                    final int step,
57                                                    final boolean realign ) throws IOException, InterruptedException {
58         final MsaCompactor mc = new MsaCompactor( msa );
59         mc.removeViaLength( length, step, realign );
60         return mc;
61     }
62
63     final private void removeGapColumns() {
64         _msa = MsaMethods.createInstance().removeGapColumns( 1, 0, _msa );
65     }
66
67     final private void removeWorstOffenders( final int to_remove, final int step, final boolean realign )
68             throws IOException, InterruptedException {
69         final DescriptiveStatistics stats[] = calcStats();
70         final List<String> to_remove_ids = new ArrayList<String>();
71         for( int j = 0; j < to_remove; ++j ) {
72             to_remove_ids.add( stats[ j ].getDescription() );
73             _removed_seq_ids.add( stats[ j ].getDescription() );
74         }
75         _msa = MsaMethods.removeSequences( _msa, to_remove_ids );
76         removeGapColumns();
77         if ( realign ) {
78             mafft();
79         }
80     }
81
82     final private void mafft() throws IOException, InterruptedException {
83         final MsaInferrer mafft = Mafft.createInstance( "/home/czmasek/bin/mafft" );
84         final List<String> opts = new ArrayList<String>();
85         opts.add( "--maxiterate" );
86         opts.add( "1000" );
87         opts.add( "--localpair" );
88         opts.add( "--quiet" );
89         _msa = mafft.infer( _msa.asSequenceList(), opts );
90     }
91
92     final private void removeViaGapAverage( final double mean_gapiness, final int step, final boolean realign )
93             throws IOException, InterruptedException {
94         if ( VERBOSE ) {
95             System.out.println( "start: " + _msa.getLength() + " "
96                     + ForesterUtil.round( MsaMethods.calcBasicGapinessStatistics( _msa ).arithmeticMean(), 3 ) );
97         }
98         int counter = 0;
99         while ( MsaMethods.calcBasicGapinessStatistics( _msa ).arithmeticMean() > mean_gapiness ) {
100             removeWorstOffenders( step, 1, false );
101             if ( realign ) {
102                 mafft();
103             }
104             if ( VERBOSE ) {
105                 System.out.println( counter + ": " + _msa.getLength() + " "
106                         + ForesterUtil.round( MsaMethods.calcBasicGapinessStatistics( _msa ).arithmeticMean(), 3 ) );
107             }
108             counter += step;
109         }
110     }
111
112     final private void removeViaLength( final int length, final int step, final boolean realign ) throws IOException,
113             InterruptedException {
114         if ( VERBOSE ) {
115             System.out.println( "start: " + _msa.getLength() + " "
116                     + ForesterUtil.round( MsaMethods.calcBasicGapinessStatistics( _msa ).arithmeticMean(), 3 ) );
117         }
118         int counter = 0;
119         while ( _msa.getLength() > length ) {
120             removeWorstOffenders( step, 1, false );
121             if ( realign ) {
122                 mafft();
123             }
124             if ( VERBOSE ) {
125                 System.out.println( counter + ": " + _msa.getLength() + " "
126                         + ForesterUtil.round( MsaMethods.calcBasicGapinessStatistics( _msa ).arithmeticMean(), 3 ) );
127             }
128             counter += step;
129         }
130     }
131
132     final private DescriptiveStatistics[] calcStats() {
133         final DescriptiveStatistics stats[] = calc();
134         sort( stats );
135         for( int i = 0; i < stats.length; ++i ) {
136             final DescriptiveStatistics s = stats[ i ];
137             //            System.out.print( s.getDescription() );
138             //            System.out.print( "\t" );
139             //            System.out.print( s.arithmeticMean() );
140             //            System.out.print( "\t(" );
141             //            System.out.print( s.arithmeticMean() );
142             //            System.out.print( ")" );
143             //            System.out.print( "\t" );
144             //            System.out.print( s.getMin() );
145             //            System.out.print( "\t" );
146             //            System.out.print( s.getMax() );
147             //            System.out.println();
148         }
149         return stats;
150     }
151
152     private final static void sort( final DescriptiveStatistics stats[] ) {
153         Arrays.sort( stats, new DescriptiveStatisticsComparator( false ) );
154     }
155
156     private final DescriptiveStatistics[] calc() {
157         final double gappiness[] = calcGappiness();
158         final DescriptiveStatistics stats[] = new DescriptiveStatistics[ _msa.getNumberOfSequences() ];
159         for( int row = 0; row < _msa.getNumberOfSequences(); ++row ) {
160             stats[ row ] = new BasicDescriptiveStatistics( _msa.getIdentifier( row ) );
161             for( int col = 0; col < _msa.getLength(); ++col ) {
162                 if ( _msa.getResidueAt( row, col ) != Sequence.GAP ) {
163                     stats[ row ].addValue( gappiness[ col ] );
164                 }
165             }
166         }
167         return stats;
168     }
169
170     private final double[] calcGappiness() {
171         final double gappiness[] = new double[ _msa.getLength() ];
172         final int seqs = _msa.getNumberOfSequences();
173         for( int i = 0; i < gappiness.length; ++i ) {
174             gappiness[ i ] = ( double ) MsaMethods.calcGapSumPerColumn( _msa, i ) / seqs;
175         }
176         return gappiness;
177     }
178
179     final static class DescriptiveStatisticsComparator implements Comparator<DescriptiveStatistics> {
180
181         final boolean _ascending;
182
183         public DescriptiveStatisticsComparator( final boolean ascending ) {
184             _ascending = ascending;
185         }
186
187         @Override
188         public final int compare( final DescriptiveStatistics s0, final DescriptiveStatistics s1 ) {
189             if ( s0.arithmeticMean() < s1.arithmeticMean() ) {
190                 return _ascending ? -1 : 1;
191             }
192             else if ( s0.arithmeticMean() > s1.arithmeticMean() ) {
193                 return _ascending ? 1 : -1;
194             }
195             return 0;
196         }
197     }
198 }