inprogress
[jalview.git] / forester / java / src / org / forester / surfacing / DomainArchitectureBasedGenomeSimilarityCalculator.java
1 // $Id:
2 // 19:38:35 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.surfacing;
28
29 import java.util.HashSet;
30 import java.util.Set;
31
32 import org.forester.protein.BinaryDomainCombination;
33
34 public class DomainArchitectureBasedGenomeSimilarityCalculator {
35
36     public static final double                MAX_SIMILARITY_SCORE = 1.0;
37     public static final double                MIN_SIMILARITY_SCORE = 0.0;
38     final private GenomeWideCombinableDomains _combinable_domains_genome_0;
39     final private GenomeWideCombinableDomains _combinable_domains_genome_1;
40     private Set<String>                       _domain_ids_to_ignore;
41     private boolean                           _allow_domains_to_be_ignored;
42     private Set<String>                       _all_domains;
43     private Set<String>                       _shared_domains;
44     private Set<String>                       _domains_specific_to_0;
45     private Set<String>                       _domains_specific_to_1;
46     private Set<BinaryDomainCombination>      _all_binary_domain_combinations;
47     private Set<BinaryDomainCombination>      _shared_binary_domain_combinations;
48     private Set<BinaryDomainCombination>      _binary_domain_combinations_specific_to_0;
49     private Set<BinaryDomainCombination>      _binary_domain_combinations_specific_to_1;
50
51     public DomainArchitectureBasedGenomeSimilarityCalculator( final GenomeWideCombinableDomains combinable_domains_genome_0,
52                                                               final GenomeWideCombinableDomains combinable_domains_genome_1 ) {
53         if ( ( combinable_domains_genome_0 == null ) || ( combinable_domains_genome_0.getSize() < 1 )
54                 || ( combinable_domains_genome_1 == null ) || ( combinable_domains_genome_1.getSize() < 1 ) ) {
55             throw new IllegalArgumentException( "attempt to compare null or empty combinable domains collection" );
56         }
57         if ( combinable_domains_genome_0.getSpecies().equals( combinable_domains_genome_1.getSpecies() ) ) {
58             throw new IllegalArgumentException( "attempt to compare combinable domains collection from the same species" );
59         }
60         _combinable_domains_genome_0 = combinable_domains_genome_0;
61         _combinable_domains_genome_1 = combinable_domains_genome_1;
62         init();
63         forceRecalculation();
64     }
65
66     public void addDomainIdToIgnore( final String domain_id_to_ignore ) {
67         forceRecalculation();
68         getDomainIdsToIgnore().add( domain_id_to_ignore );
69     }
70
71     /**
72      * This returns a score between 0.0 (no binary domain combination in common) 
73      * and 1.0 (all binary domain combinations in common) measuring the similarity between two
74      * genomes based on the number of shared binary domain combinations:
75      *   
76      * t: sum of (distinct) binary domain combinations
77      * s: sum of shared (distinct) binary domain combinations
78      *
79      * 1 - ( ( t - s ) / t )
80      *  
81      * @return shared binary domain combinations based similarity score 
82      */
83     public double calculateSharedBinaryDomainCombinationBasedGenomeSimilarityScore() {
84         final double t = getAllBinaryDomainCombinations().size();
85         final double s = getSharedBinaryDomainCombinations().size();
86         if ( t == 0.0 ) {
87             return MIN_SIMILARITY_SCORE;
88         }
89         return ( MAX_SIMILARITY_SCORE - ( ( t - s ) / t ) );
90     }
91
92     /**
93      * This returns a score between 0.0 (no domains in common) 
94      * and 1.0 (all domains in common) measuring the similarity between two
95      * genomes based on the number of shared domains:
96      * 
97      * t: sum of (distinct) domains
98      * s: sum of shared (distinct) domains
99      *
100      * 1 - ( ( t - s ) / t )
101      * 
102      * @return shared domains based similarity score 
103      */
104     public double calculateSharedDomainsBasedGenomeSimilarityScore() {
105         final double t = getAllDomains().size();
106         final double s = getSharedDomains().size();
107         if ( t == 0.0 ) {
108             return MIN_SIMILARITY_SCORE;
109         }
110         return ( MAX_SIMILARITY_SCORE - ( ( t - s ) / t ) );
111     }
112
113     public void deleteAllDomainIdsToIgnore() {
114         forceRecalculation();
115         setDomainIdsToIgnore( new HashSet<String>() );
116     }
117
118     private void forceRecalculation() {
119         _all_domains = null;
120         _shared_domains = null;
121         _domains_specific_to_0 = null;
122         _domains_specific_to_1 = null;
123         _all_binary_domain_combinations = null;
124         _shared_binary_domain_combinations = null;
125         _binary_domain_combinations_specific_to_0 = null;
126         _binary_domain_combinations_specific_to_1 = null;
127     }
128
129     /**
130      * Does not return binary combinations which contain one or two domains
131      * to be ignored -- if ignoring is allowed.
132      * 
133      * @return SortedSet<BinaryDomainCombination>
134      */
135     public Set<BinaryDomainCombination> getAllBinaryDomainCombinations() {
136         if ( _all_binary_domain_combinations == null ) {
137             final Set<BinaryDomainCombination> all = new HashSet<BinaryDomainCombination>();
138             all.addAll( getCombinableDomainsGenome0().toBinaryDomainCombinations() );
139             all.addAll( getCombinableDomainsGenome1().toBinaryDomainCombinations() );
140             if ( isAllowDomainsToBeIgnored() && !getDomainIdsToIgnore().isEmpty() ) {
141                 _all_binary_domain_combinations = pruneBinaryCombinations( all );
142             }
143             else {
144                 _all_binary_domain_combinations = all;
145             }
146         }
147         return _all_binary_domain_combinations;
148     }
149
150     /**
151      * Does not return domains which are to be
152      * ignored -- if ignoring is allowed.
153      * 
154      * 
155      * @return
156      */
157     public Set<String> getAllDomains() {
158         if ( _all_domains == null ) {
159             final Set<String> all = new HashSet<String>();
160             all.addAll( getCombinableDomainsGenome0().getAllDomainIds() );
161             all.addAll( getCombinableDomainsGenome1().getAllDomainIds() );
162             if ( isAllowDomainsToBeIgnored() && !getDomainIdsToIgnore().isEmpty() ) {
163                 _all_domains = pruneDomains( all );
164             }
165             else {
166                 _all_domains = all;
167             }
168         }
169         return _all_domains;
170     }
171
172     private Set<BinaryDomainCombination> getBinaryDomainCombinationsSpecificToGenome( final boolean specific_to_genome_0 ) {
173         final Set<BinaryDomainCombination> specific = new HashSet<BinaryDomainCombination>();
174         final Set<BinaryDomainCombination> bc0 = getCombinableDomainsGenome0().toBinaryDomainCombinations();
175         final Set<BinaryDomainCombination> bc1 = getCombinableDomainsGenome1().toBinaryDomainCombinations();
176         if ( specific_to_genome_0 ) {
177             for( final BinaryDomainCombination binary_domain_combination0 : bc0 ) {
178                 if ( !bc1.contains( binary_domain_combination0 ) ) {
179                     specific.add( binary_domain_combination0 );
180                 }
181             }
182         }
183         else {
184             for( final BinaryDomainCombination binary_domain_combination1 : bc1 ) {
185                 if ( !bc0.contains( binary_domain_combination1 ) ) {
186                     specific.add( binary_domain_combination1 );
187                 }
188             }
189         }
190         if ( isAllowDomainsToBeIgnored() && !getDomainIdsToIgnore().isEmpty() ) {
191             return pruneBinaryCombinations( specific );
192         }
193         return specific;
194     }
195
196     public Set<BinaryDomainCombination> getBinaryDomainCombinationsSpecificToGenome0() {
197         if ( _binary_domain_combinations_specific_to_0 == null ) {
198             _binary_domain_combinations_specific_to_0 = getBinaryDomainCombinationsSpecificToGenome( true );
199         }
200         return _binary_domain_combinations_specific_to_0;
201     }
202
203     public Set<BinaryDomainCombination> getBinaryDomainCombinationsSpecificToGenome1() {
204         if ( _binary_domain_combinations_specific_to_1 == null ) {
205             _binary_domain_combinations_specific_to_1 = getBinaryDomainCombinationsSpecificToGenome( false );
206         }
207         return _binary_domain_combinations_specific_to_1;
208     }
209
210     private GenomeWideCombinableDomains getCombinableDomainsGenome0() {
211         return _combinable_domains_genome_0;
212     }
213
214     private GenomeWideCombinableDomains getCombinableDomainsGenome1() {
215         return _combinable_domains_genome_1;
216     }
217
218     private Set<String> getDomainIdsToIgnore() {
219         return _domain_ids_to_ignore;
220     }
221
222     private Set<String> getDomainsSpecificToGenome( final boolean specific_to_genome_0 ) {
223         final Set<String> specific = new HashSet<String>();
224         final Set<String> d0 = getCombinableDomainsGenome0().getAllDomainIds();
225         final Set<String> d1 = getCombinableDomainsGenome1().getAllDomainIds();
226         if ( specific_to_genome_0 ) {
227             for( final String domain0 : d0 ) {
228                 if ( !d1.contains( domain0 ) ) {
229                     specific.add( domain0 );
230                 }
231             }
232         }
233         else {
234             for( final String domain1 : d1 ) {
235                 if ( !d0.contains( domain1 ) ) {
236                     specific.add( domain1 );
237                 }
238             }
239         }
240         if ( isAllowDomainsToBeIgnored() && !getDomainIdsToIgnore().isEmpty() ) {
241             return pruneDomains( specific );
242         }
243         return specific;
244     }
245
246     public Set<String> getDomainsSpecificToGenome0() {
247         if ( _domains_specific_to_0 == null ) {
248             _domains_specific_to_0 = getDomainsSpecificToGenome( true );
249         }
250         return _domains_specific_to_0;
251     }
252
253     public Set<String> getDomainsSpecificToGenome1() {
254         if ( _domains_specific_to_1 == null ) {
255             _domains_specific_to_1 = getDomainsSpecificToGenome( false );
256         }
257         return _domains_specific_to_1;
258     }
259
260     public Set<BinaryDomainCombination> getSharedBinaryDomainCombinations() {
261         if ( _shared_binary_domain_combinations == null ) {
262             final Set<BinaryDomainCombination> shared = new HashSet<BinaryDomainCombination>();
263             final Set<BinaryDomainCombination> bc0 = getCombinableDomainsGenome0().toBinaryDomainCombinations();
264             final Set<BinaryDomainCombination> bc1 = getCombinableDomainsGenome1().toBinaryDomainCombinations();
265             for( final BinaryDomainCombination binary_domain_combination0 : bc0 ) {
266                 if ( bc1.contains( binary_domain_combination0 ) ) {
267                     shared.add( binary_domain_combination0 );
268                 }
269             }
270             _shared_binary_domain_combinations = shared;
271             if ( isAllowDomainsToBeIgnored() && !getDomainIdsToIgnore().isEmpty() ) {
272                 _shared_binary_domain_combinations = pruneBinaryCombinations( shared );
273             }
274         }
275         return _shared_binary_domain_combinations;
276     }
277
278     public Set<String> getSharedDomains() {
279         if ( _shared_domains == null ) {
280             final Set<String> shared = new HashSet<String>();
281             final Set<String> d0 = getCombinableDomainsGenome0().getAllDomainIds();
282             final Set<String> d1 = getCombinableDomainsGenome1().getAllDomainIds();
283             for( final String domain0 : d0 ) {
284                 if ( d1.contains( domain0 ) ) {
285                     shared.add( domain0 );
286                 }
287             }
288             _shared_domains = shared;
289             if ( isAllowDomainsToBeIgnored() && !getDomainIdsToIgnore().isEmpty() ) {
290                 _shared_domains = pruneDomains( shared );
291             }
292         }
293         return _shared_domains;
294     }
295
296     private void init() {
297         deleteAllDomainIdsToIgnore();
298         setAllowDomainsToBeIgnored( false );
299     }
300
301     private boolean isAllowDomainsToBeIgnored() {
302         return _allow_domains_to_be_ignored;
303     }
304
305     private Set<BinaryDomainCombination> pruneBinaryCombinations( final Set<BinaryDomainCombination> all ) {
306         final Set<BinaryDomainCombination> pruned = new HashSet<BinaryDomainCombination>();
307         for( final BinaryDomainCombination bc : all ) {
308             if ( ( !getDomainIdsToIgnore().contains( bc.getId0() ) )
309                     && ( !getDomainIdsToIgnore().contains( bc.getId1() ) ) ) {
310                 pruned.add( bc );
311             }
312         }
313         return pruned;
314     }
315
316     private Set<String> pruneDomains( final Set<String> all ) {
317         final Set<String> pruned = new HashSet<String>();
318         for( final String d : all ) {
319             if ( !getDomainIdsToIgnore().contains( d ) ) {
320                 pruned.add( d );
321             }
322         }
323         return pruned;
324     }
325
326     public void setAllowDomainsToBeIgnored( final boolean allow_domains_to_be_ignored ) {
327         forceRecalculation();
328         _allow_domains_to_be_ignored = allow_domains_to_be_ignored;
329     }
330
331     void setDomainIdsToIgnore( final Set<String> domain_ids_to_ignore ) {
332         forceRecalculation();
333         _domain_ids_to_ignore = domain_ids_to_ignore;
334     }
335 }