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() );
110 public StringBuffer asSimpleText() {
111 final StringBuffer sb = new StringBuffer();
112 if ( isUnassigned() ) {
114 else if ( isSpeciationOrDuplication() ) {
117 else if ( isOther() || isRoot() || isTransfer() || isFusion() ) {
118 sb.append( getEventType().toString() );
121 if ( getNumberOfDuplications() > 0 ) {
122 if ( getNumberOfDuplications() > 1 ) {
123 sb.append( getNumberOfDuplications() );
127 if ( getNumberOfSpeciations() > 0 ) {
128 if ( getNumberOfSpeciations() > 1 ) {
129 sb.append( getNumberOfSpeciations() );
133 if ( getNumberOfGeneLosses() > 0 ) {
134 if ( getNumberOfGeneLosses() > 1 ) {
135 sb.append( getNumberOfGeneLosses() );
143 public StringBuffer asText() {
144 final StringBuffer sb = new StringBuffer();
145 if ( isUnassigned() || isSpeciationOrDuplication() || isOther() || isRoot() || isTransfer() || isFusion() ) {
146 sb.append( getEventType().toString() );
149 if ( isDuplication() ) {
150 if ( getNumberOfDuplications() == 1 ) {
151 sb.append( "duplication" );
154 sb.append( "duplications [" + getNumberOfDuplications() + "]" );
157 else if ( isSpeciation() ) {
158 if ( getNumberOfSpeciations() == 1 ) {
159 sb.append( "speciation" );
162 sb.append( "speciations [" + getNumberOfSpeciations() + "]" );
165 else if ( isGeneLoss() ) {
166 if ( getNumberOfGeneLosses() == 1 ) {
167 sb.append( "gene-loss" );
170 sb.append( "gene-losses [" + getNumberOfGeneLosses() + "]" );
174 sb.append( "duplications [" + getNumberOfDuplications() + "] " );
175 sb.append( "speciations [" + getNumberOfSpeciations() + "] " );
176 sb.append( "gene-losses [" + getNumberOfGeneLosses() + "]" );
182 public PhylogenyData copy() {
183 if ( isUnassigned() ) {
186 else if ( _event_type != EventType.mixed ) {
187 return new Event( _event_type );
190 return new Event( _duplications, _speciations, _gene_losses );
194 public Confidence getConfidence() {
198 public EventType getEventType() {
202 public int getNumberOfDuplications() {
203 return _duplications;
206 public int getNumberOfGeneLosses() {
210 public int getNumberOfSpeciations() {
215 * Returns true if this event contains one or more duplications events only
217 * @return true if this event contains one or more duplications events only
219 public boolean isDuplication() {
220 return ( _duplications > 0 ) && ( _gene_losses < 1 ) && ( _speciations < 1 );
223 public boolean isEqual( final PhylogenyData event ) {
224 if ( ( event == null ) || !( event instanceof Event ) ) {
227 final Event e = ( Event ) event;
228 if ( getEventType().compareTo( e.getEventType() ) != 0 ) {
231 if ( getNumberOfDuplications() != e.getNumberOfDuplications() ) {
234 if ( getNumberOfSpeciations() != e.getNumberOfSpeciations() ) {
237 if ( getNumberOfGeneLosses() != e.getNumberOfGeneLosses() ) {
243 public boolean isFusion() {
244 return _event_type == EventType.fusion;
248 * Returns true if this event contains one or more gene loss events only
250 * @return true if this event contains one or more gene loss events only
252 public boolean isGeneLoss() {
253 return ( _duplications < 1 ) && ( _gene_losses > 0 ) && ( _speciations < 1 );
256 public boolean isOther() {
257 return _event_type == EventType.other;
260 public boolean isRoot() {
261 return _event_type == EventType.root;
265 * Returns true if this event contains one or more speciation events only
267 * @return true if this event contains one or more speciation events only
269 public boolean isSpeciation() {
270 return ( _duplications < 1 ) && ( _gene_losses < 1 ) && ( _speciations > 0 );
273 public boolean isSpeciationOrDuplication() {
274 return _event_type == EventType.speciation_or_duplication;
277 public boolean isTransfer() {
278 return _event_type == EventType.transfer;
281 public boolean isUnassigned() {
282 return ( _duplications == DEFAULT_VALUE ) && ( _event_type == EventType.unassigned );
285 public void setConfidence( final Confidence confidence ) {
286 _confidence = confidence;
289 public void setDuplications( final int duplications ) {
290 _duplications = duplications;
291 _event_type = EventType.mixed;
294 public void setGeneLosses( final int gene_losses ) {
295 _gene_losses = gene_losses;
296 _event_type = EventType.mixed;
299 public void setSpeciations( final int speciations ) {
300 _speciations = speciations;
301 _event_type = EventType.mixed;
304 public StringBuffer toNHX() {
305 final StringBuffer sb = new StringBuffer();
306 if ( !isUnassigned() && ( isSpeciationOrDuplication() || isDuplication() || isSpeciation() ) ) {
308 sb.append( NHXtags.IS_DUPLICATION );
309 if ( isSpeciationOrDuplication() ) {
312 else if ( isDuplication() ) {
315 else if ( isSpeciation() ) {
322 public void toPhyloXML( final Writer writer, final int level, final String indentation ) throws IOException {
323 writer.write( ForesterUtil.LINE_SEPARATOR );
324 writer.write( indentation );
325 PhylogenyDataUtil.appendOpen( writer, PhyloXmlMapping.EVENTS );
326 if ( ( getEventType() != EventType.unassigned ) && ( getEventType() != EventType.mixed ) ) {
328 .appendElement( writer, PhyloXmlMapping.EVENT_TYPE, getEventType().toString(), indentation );
330 if ( getNumberOfDuplications() > 0 ) {
331 PhylogenyDataUtil.appendElement( writer,
332 PhyloXmlMapping.EVENT_DUPLICATIONS,
333 getNumberOfDuplications() + "",
336 if ( getNumberOfSpeciations() > 0 ) {
337 PhylogenyDataUtil.appendElement( writer,
338 PhyloXmlMapping.EVENT_SPECIATIONS,
339 getNumberOfSpeciations() + "",
342 if ( getNumberOfGeneLosses() > 0 ) {
343 PhylogenyDataUtil.appendElement( writer,
344 PhyloXmlMapping.EVENT_LOSSES,
345 getNumberOfGeneLosses() + "",
348 if ( getConfidence() != null ) {
349 getConfidence().toPhyloXML( writer, level, indentation + PhylogenyWriter.PHYLO_XML_INTENDATION_BASE );
351 writer.write( ForesterUtil.LINE_SEPARATOR );
352 writer.write( indentation );
353 PhylogenyDataUtil.appendClose( writer, PhyloXmlMapping.EVENTS );
357 public String toString() {
358 return asText().toString();
361 public static Event createSingleDuplicationEvent() {
362 return new Event( 1, 0, 0 );
365 public static Event createSingleSpeciationEvent() {
366 return new Event( 0, 1, 0 );
369 public static Event createSingleSpeciationOrDuplicationEvent() {
370 return new Event( EventType.speciation_or_duplication );
373 public static enum EventType {
374 transfer, fusion, root, speciation_or_duplication, other, mixed, unassigned