2 // FORESTER -- software libraries and applications
3 // for evolutionary biology research and applications.
5 // Copyright (C) 2008-2009 Christian M. Zmasek
6 // Copyright (C) 2008-2009 Burnham Institute for Medical Research
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 // Contact: phylosoft @ gmail . com
24 // WWW: www.phylosoft.org/forester
26 package org.forester.phylogeny.data;
28 import java.io.IOException;
29 import java.io.Writer;
30 import java.util.StringTokenizer;
32 import org.forester.io.parsers.nhx.NHXFormatException;
33 import org.forester.io.parsers.nhx.NHXtags;
34 import org.forester.io.parsers.phyloxml.PhyloXmlMapping;
35 import org.forester.io.writers.PhylogenyWriter;
36 import org.forester.util.ForesterUtil;
38 public class Event implements PhylogenyData {
40 public final static int DEFAULT_VALUE = -1;
41 private static final String NHX_SEPARATOR = ">";
42 private int _duplications;
43 private int _speciations;
44 private int _gene_losses;
45 private EventType _event_type;
46 private Confidence _confidence;
49 _duplications = DEFAULT_VALUE;
50 _speciations = DEFAULT_VALUE;
51 _gene_losses = DEFAULT_VALUE;
52 _event_type = EventType.unassigned;
55 public Event( final EventType type ) {
56 _duplications = DEFAULT_VALUE;
57 _speciations = DEFAULT_VALUE;
58 _gene_losses = DEFAULT_VALUE;
62 public Event( final int duplications, final int speciations, final int gene_losses ) {
63 _duplications = duplications;
64 _speciations = speciations;
65 _gene_losses = gene_losses;
66 _event_type = EventType.mixed;
69 public Event( final int duplications, final int speciations, final int gene_losses, final String type ) {
70 _duplications = duplications;
71 _speciations = speciations;
72 _gene_losses = gene_losses;
73 _event_type = EventType.valueOf( type );
76 public Event( final String nhx ) throws NHXFormatException {
77 if ( ForesterUtil.isEmpty( nhx ) ) {
78 _duplications = DEFAULT_VALUE;
79 _speciations = DEFAULT_VALUE;
80 _gene_losses = DEFAULT_VALUE;
81 _event_type = EventType.unassigned;
84 final StringTokenizer st = new StringTokenizer( nhx, NHX_SEPARATOR );
85 if ( st.countTokens() != 4 ) {
86 throw new NHXFormatException( "malformed NHX format for event [" + nhx + "]" );
88 final String duplications = ( String ) st.nextElement();
89 final String speciations = ( String ) st.nextElement();
90 final String losses = ( String ) st.nextElement();
91 final String event_type = ( String ) st.nextElement();
96 d = Integer.parseInt( duplications );
97 s = Integer.parseInt( speciations );
98 l = Integer.parseInt( losses );
102 _event_type = EventType.valueOf( event_type );
104 catch ( final Exception e ) {
105 throw new NHXFormatException( "malformed NHX format for event [" + nhx + "]:" + e.getMessage() );
111 public StringBuffer asSimpleText() {
112 final StringBuffer sb = new StringBuffer();
113 if ( isUnassigned() ) {
115 else if ( isSpeciationOrDuplication() ) {
118 else if ( isOther() || isRoot() || isTransfer() || isFusion() ) {
119 sb.append( getEventType().toString() );
122 if ( getNumberOfDuplications() > 0 ) {
123 if ( getNumberOfDuplications() > 1 ) {
124 sb.append( getNumberOfDuplications() );
128 if ( getNumberOfSpeciations() > 0 ) {
129 if ( getNumberOfSpeciations() > 1 ) {
130 sb.append( getNumberOfSpeciations() );
134 if ( getNumberOfGeneLosses() > 0 ) {
135 if ( getNumberOfGeneLosses() > 1 ) {
136 sb.append( getNumberOfGeneLosses() );
145 public StringBuffer asText() {
146 final StringBuffer sb = new StringBuffer();
147 if ( isUnassigned() || isSpeciationOrDuplication() || isOther() || isRoot() || isTransfer() || isFusion() ) {
148 sb.append( getEventType().toString() );
151 if ( isDuplication() ) {
152 if ( getNumberOfDuplications() == 1 ) {
153 sb.append( "duplication" );
156 sb.append( "duplications [" + getNumberOfDuplications() + "]" );
159 else if ( isSpeciation() ) {
160 if ( getNumberOfSpeciations() == 1 ) {
161 sb.append( "speciation" );
164 sb.append( "speciations [" + getNumberOfSpeciations() + "]" );
167 else if ( isGeneLoss() ) {
168 if ( getNumberOfGeneLosses() == 1 ) {
169 sb.append( "gene-loss" );
172 sb.append( "gene-losses [" + getNumberOfGeneLosses() + "]" );
176 sb.append( "duplications [" + getNumberOfDuplications() + "] " );
177 sb.append( "speciations [" + getNumberOfSpeciations() + "] " );
178 sb.append( "gene-losses [" + getNumberOfGeneLosses() + "]" );
185 public PhylogenyData copy() {
186 if ( isUnassigned() ) {
189 else if ( _event_type != EventType.mixed ) {
190 return new Event( _event_type );
193 return new Event( _duplications, _speciations, _gene_losses );
197 public Confidence getConfidence() {
201 public EventType getEventType() {
205 public int getNumberOfDuplications() {
206 return _duplications;
209 public int getNumberOfGeneLosses() {
213 public int getNumberOfSpeciations() {
218 * Returns true if this event contains one or more duplications events only
220 * @return true if this event contains one or more duplications events only
222 public boolean isDuplication() {
223 return ( _duplications > 0 ) && ( _gene_losses < 1 ) && ( _speciations < 1 );
227 public boolean isEqual( final PhylogenyData event ) {
228 if ( ( event == null ) || !( event instanceof Event ) ) {
231 final Event e = ( Event ) event;
232 if ( getEventType().compareTo( e.getEventType() ) != 0 ) {
235 if ( getNumberOfDuplications() != e.getNumberOfDuplications() ) {
238 if ( getNumberOfSpeciations() != e.getNumberOfSpeciations() ) {
241 if ( getNumberOfGeneLosses() != e.getNumberOfGeneLosses() ) {
247 public boolean isFusion() {
248 return _event_type == EventType.fusion;
252 * Returns true if this event contains one or more gene loss events only
254 * @return true if this event contains one or more gene loss events only
256 public boolean isGeneLoss() {
257 return ( _duplications < 1 ) && ( _gene_losses > 0 ) && ( _speciations < 1 );
260 public boolean isOther() {
261 return _event_type == EventType.other;
264 public boolean isRoot() {
265 return _event_type == EventType.root;
269 * Returns true if this event contains one or more speciation events only
271 * @return true if this event contains one or more speciation events only
273 public boolean isSpeciation() {
274 return ( _duplications < 1 ) && ( _gene_losses < 1 ) && ( _speciations > 0 );
277 public boolean isSpeciationOrDuplication() {
278 return _event_type == EventType.speciation_or_duplication;
281 public boolean isTransfer() {
282 return _event_type == EventType.transfer;
285 public boolean isUnassigned() {
286 return ( _duplications == DEFAULT_VALUE ) && ( _event_type == EventType.unassigned );
289 public void setConfidence( final Confidence confidence ) {
290 _confidence = confidence;
293 public void setDuplications( final int duplications ) {
294 _duplications = duplications;
295 _event_type = EventType.mixed;
298 public void setGeneLosses( final int gene_losses ) {
299 _gene_losses = gene_losses;
300 _event_type = EventType.mixed;
303 public void setSpeciations( final int speciations ) {
304 _speciations = speciations;
305 _event_type = EventType.mixed;
309 public StringBuffer toNHX() {
310 final StringBuffer sb = new StringBuffer();
311 if ( !isUnassigned() && ( isSpeciationOrDuplication() || isDuplication() || isSpeciation() ) ) {
313 sb.append( NHXtags.IS_DUPLICATION );
314 if ( isSpeciationOrDuplication() ) {
317 else if ( isDuplication() ) {
320 else if ( isSpeciation() ) {
328 public void toPhyloXML( final Writer writer, final int level, final String indentation ) throws IOException {
329 writer.write( ForesterUtil.LINE_SEPARATOR );
330 writer.write( indentation );
331 PhylogenyDataUtil.appendOpen( writer, PhyloXmlMapping.EVENTS );
332 if ( ( getEventType() != EventType.unassigned ) && ( getEventType() != EventType.mixed ) ) {
334 .appendElement( writer, PhyloXmlMapping.EVENT_TYPE, getEventType().toString(), indentation );
336 if ( getNumberOfDuplications() > 0 ) {
337 PhylogenyDataUtil.appendElement( writer,
338 PhyloXmlMapping.EVENT_DUPLICATIONS,
339 getNumberOfDuplications() + "",
342 if ( getNumberOfSpeciations() > 0 ) {
343 PhylogenyDataUtil.appendElement( writer,
344 PhyloXmlMapping.EVENT_SPECIATIONS,
345 getNumberOfSpeciations() + "",
348 if ( getNumberOfGeneLosses() > 0 ) {
349 PhylogenyDataUtil.appendElement( writer,
350 PhyloXmlMapping.EVENT_LOSSES,
351 getNumberOfGeneLosses() + "",
354 if ( getConfidence() != null ) {
355 getConfidence().toPhyloXML( writer, level, indentation + PhylogenyWriter.PHYLO_XML_INTENDATION_BASE );
357 writer.write( ForesterUtil.LINE_SEPARATOR );
358 writer.write( indentation );
359 PhylogenyDataUtil.appendClose( writer, PhyloXmlMapping.EVENTS );
363 public String toString() {
364 return asText().toString();
367 public static Event createSingleDuplicationEvent() {
368 return new Event( 1, 0, 0 );
371 public static Event createSingleSpeciationEvent() {
372 return new Event( 0, 1, 0 );
375 public static Event createSingleSpeciationOrDuplicationEvent() {
376 return new Event( EventType.speciation_or_duplication );
379 public static enum EventType {
380 transfer, fusion, root, speciation_or_duplication, other, mixed, unassigned