BioInfWeb - JPhyloIO / Source code / Show File - AlignmentReader.java

JPhyloIO subversion repository

sventon subversion web client - http://www.sventon.org
[show recent changes]
 
  Help
Rev: HEAD (1579) - https://secure.bioinfweb.info/Code/svn/JPhyloIO / trunk / demo / info.bioinfweb.jphyloio.demo.simplealignment / src / info / bioinfweb / jphyloio / demo / simplealignment / AlignmentReader.java
Show File - AlignmentReader.java  [show properties]
spinner
/*
 * JPhyloIO - Event based parsing and stream writing of multiple sequence alignment and tree formats. 
 * Copyright (C) 2015-2016  Ben Stöver, Sarah Wiechers
 * <http://bioinfweb.info/JPhyloIO>
 * 
 * This file is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
10   * 
11   * This file is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14   * GNU Lesser General Public License for more details.
15   * 
16   * You should have received a copy of the GNU Lesser General Public License
17   * along with this program. If not, see <http://www.gnu.org/licenses/>.
18   */
19  package info.bioinfweb.jphyloio.demo.simplealignment;
20 
21 
22  import info.bioinfweb.jphyloio.JPhyloIOEventReader;
23  import info.bioinfweb.jphyloio.events.JPhyloIOEvent;
24  import info.bioinfweb.jphyloio.events.LinkedLabeledIDEvent;
25  import info.bioinfweb.jphyloio.events.type.EventContentType;
26  import info.bioinfweb.jphyloio.events.type.EventTopologyType;
27  import info.bioinfweb.jphyloio.utils.JPhyloIOReadingUtils;
28 
29  import java.io.IOException;
30  import java.util.HashMap;
31  import java.util.List;
32  import java.util.Map;
33 
34 
35 
36  /**
37   * This is the <i>JPhyloIO</i> reader of this demo application that connects the readers available in <i>JPhyloIO</i> with the
38   * business model of the application by extracting relevant data from the <i>JPhyloIO</i> event sequence and storing it in the 
39   * application model.
40   * <p>
41   * Each application based on <i>JPhyloIO</i> needs to implement one such reader to support all available formats. The application 
42   * can use this reader by calling {@link #read(JPhyloIOEventReader, Map)}.
43   * <p>
44   * Each method in this reader handles a sequence of events nested between a start and end event. Although there are alternatives,
45   * this is usually a good way to implement pull parsing. Each of these methods corresponds to a grammar node of the <i>JPhyloIO</i>
46   * event sequence that can be found in the documentation of {@link JPhyloIOEventReader}. 
47   * 
48   * @author Ben St&ouml;ver
49   */
50  public class AlignmentReader {
51      /** Stores the <i>JPhyloIO</i> event reader that is currently used by this instance. */
52      private JPhyloIOEventReader reader;
53      
54      /** Stores the application model that is the current target for data read by this instance. */
55      private ApplicationModel model;
56      
57      /** Map that is used internally to map <i>JPhyloIO</i> sequence IDs to indices in the application business model. */
58      private Map<String, Integer> sequenceIDMap = new HashMap<String, Integer>();
59      
60      
61      /**
62       * Main method of this reader. It reads an alignment using the specified <i>JPhyloIO</i> reader to the specified application 
63       * business model.
64       * <p>
65       * The loop in this method processes the event sequence defined by the <i>JPhyloIO</i> grammar node <code>Document</code>. 
66       * (The grammar can be found in the documentation of {@link JPhyloIOEventReader}.)
67       * 
68       * @param reader the <i>JPhyloIO</i> reader providing the event stream to be processed
69       * @param model the application business model to take up the loaded alignment data
70       * @throws IOException exceptions thrown during the I/O operation
71       */
72      public void read(JPhyloIOEventReader reader, ApplicationModel model) 
73              throws IOException {  // Possible exceptions from JPhyloIO readers are forwarded.
74          
75          // Store parameters in instance variables to have them available in all methods:
76          this.reader = reader;
77          this.model = model;
78          sequenceIDMap.clear();  // Remove entries from the list from possible previous calls of this method. 
79          
80          // Process JPhyloIO events:
81          while (reader.hasNextEvent()) {  // This loop will run until all events of the JPhyloIO reader are consumed (and the end of the 
82                                             // document is reached). 
83              JPhyloIOEvent event = reader.next();  // Read the next event from the JPhyloIO reader.        
84        switch (event.getType().getContentType()) {  // This switch statement handles all types of elements on the top level that are 
85                                                     // relevant for this application. The others are skipped in the default block. 
86          case DOCUMENT:
87              if (event.getType().getTopologyType().equals(EventTopologyType.START)) {  // There can be a document start and a document end event.
88                  model.clear();  // Remove possible previous data from the model instance.
89              }
90              // Document end events do not need any treatment in this application.
91              break;
92              
93          case ALIGNMENT:
94              if (event.getType().getTopologyType().equals(EventTopologyType.START)) {  // There can be a document start and a document end event.
95                  if (model.isEmpty()) {
96                      readAlignment(event.asLinkedLabeledIDEvent());  // Delegate reading the alignment contents to another method 
97                                                                      // (that corresponds to a nested grammar node).
98                  }
99                  else {
100                      System.out.println("Since this application does not support multiple alignments, the alignment with the ID "
101                              + event.asLinkedLabeledIDEvent().getID() + " was skipped.");
102                  }
103              }
104              break;
105              
106          default:  // Here possible additional events on the top level are handled (e.g. tree group events).
107              JPhyloIOReadingUtils.reachElementEnd(reader);  // This tool method will skip over all elements until the end event to the
108                                                             // current event was read. This way all nested events not relevant for this
109                                                             // application are skipped. If the current event would have the topology
110                                                             // type SOLE, the method will skip no additional events.
111              break;
112        }
113          }
114      }
115      
116      
117      /**
118       * This method reads the contents of an alignment to the application business model.
119       * <p>
120       * The loop in this method processes the event sequence defined by the <i>JPhyloIO</i> grammar node <code>Matrix</code>. (The 
121       * grammar can be found in the documentation of {@link JPhyloIOEventReader}.)
122       * 
123       * @param alignmentStartEvent the start event of the alignment to be read 
124       * @throws IOException exceptions thrown during the I/O operation
125       */
126      private void readAlignment(LinkedLabeledIDEvent alignmentStartEvent) throws IOException {
127          // Load label:
128          model.setLabel(alignmentStartEvent.getLabel());  // If no label was read, it will be set to null.
129          
130          // Process JPhyloIO events:
131          JPhyloIOEvent event = reader.next();  
132          while ((!event.getType().getTopologyType().equals(EventTopologyType.END))) {  // This loop will run until all events for the 
133                                                                                          // current alignment are consumed. 
134        if (event.getType().getContentType().equals(EventContentType.SEQUENCE)) {  // This application is only interested in sequence events 
135                                                                                   // and will skip others on this level (e.g. character set 
136                                                                                   // or sequence set definitions).
137          readSequencePart(event.asLinkedLabeledIDEvent());  // Delegate reading the sequence contents to another method.
138        }
139        else {
140          JPhyloIOReadingUtils.reachElementEnd(reader);  // Skip events not processed by this application.
141        }
142              event = reader.next();  // Read the next event from the JPhyloIO reader.          
143          }
144      }
145      
146      
147      /**
148       * Reads the contents (tokens) of a sequence (part).
149       * <p>
150       * Note that JPhyloIO allows to split sequences into multiple parts (i.e. multiple sequence start events with the same ID).
151       * If an ID is encountered the second time, contained tokens must be appended to the current sequence. The JPhyloIO grammar
152       * allows this to be able to efficiently process interleaved formats versions (of e.g. Nexus or Phylip). Selecting or creating 
153       * the correct sequence object is handled by {@link #getTokenList(String)}.
154       * <p>
155       * The loop in this method processes the event sequence defined by the <i>JPhyloIO</i> grammar node <code>SequencePart</code>. 
156       * (The grammar can be found in the documentation of {@link JPhyloIOEventReader}.)
157       * 
158       * @param sequenceID the ID of the sequence to be read
159       * @throws IOException 
160       */
161      private void readSequencePart(LinkedLabeledIDEvent sequencePartStartEvent) throws IOException {
162          List<String> sequence = getTokenList(sequencePartStartEvent);  // Fetch an existing or create a new token list from the model.
163          
164          JPhyloIOEvent event = reader.next();  
165          while ((!event.getType().getTopologyType().equals(EventTopologyType.END))) { 
166              switch (event.getType().getContentType()) { 
167                  case SEQUENCE_TOKENS:  // This event always has the topology type SOLE, so there is no further if-statement necessary. 
168                      sequence.addAll(event.asSequenceTokensEvent().getTokens());  // Append the tokens from this event to the current sequence. 
169                      break;
170                      
171                  case SINGLE_SEQUENCE_TOKEN:  // As an alternative to the SEQUENCE_TOKENS event that contains a list of tokens, JPhyloIO also 
172                                                 // allows to represents a single tokens in one event to be able to nest metadata of that token.
173                      sequence.add(event.asSingleSequenceTokenEvent().getToken());  // Append the tokens from this event to the current sequence.
174                                                                                    // No check of the topology type is required here, since the 
175                                                                                    // first event will always be the start event and the end 
176                                                                                    // event will directly be consumed in the next line.
177                      JPhyloIOReadingUtils.reachElementEnd(reader);  // Skip all events nested under this event and the respective end event.
178                      break;
179                      
180                  default:
181                      JPhyloIOReadingUtils.reachElementEnd(reader);  // Skip possible events on this level, the application is not interested in.
182                      break;
183              }
184              event = reader.next();        
185          }
186      }
187      
188      
189      /**
190       * Returns the token list for the sequence associated with the specified <i>JPhyloIO</i> sequence ID from the application model. 
191       * If none associated with the specified ID is currently present, a new one will be created, added to the model and returned.
192       * 
193       * @param sequencePartStartEvent the event describing the sequence
194       * @return the token list object for the requested sequence from the model
195       */
196      private List<String> getTokenList(LinkedLabeledIDEvent sequencePartStartEvent) {
197          Integer index = sequenceIDMap.get(sequencePartStartEvent.getID());  // Determine the index of the sequence associated with the 
198                                                                          // current ID in the application model.  
199          if (index == null) {  // If this sequence ID was not encountered until now:
200            // Add a new sequence to the model and 
201              index = model.addSequence(sequencePartStartEvent.getLabel());  // Add a new sequence to the model
202              sequenceIDMap.put(sequencePartStartEvent.getID(), index);  // Map its index to its ID. 
203          }
204          return model.getSequenceTokens(index);  //
205      }
206  }


feed icon

sventon 2.5.1

Valid XHTML 1.0 Strict   CSS ist valide!
JPhyloIO icon
bioinfweb RSS feed JPhyloIO on ResearchGate bioinfweb on twitter JPhyloIO on GitHub

JPhyloIO poster ECCB 2016 Conference poster at ECCB Sep 2016

bioinfweb - Biology & Informatics Website