MATSIM
VisumMatrixReader.java
Go to the documentation of this file.
1 /* *********************************************************************** *
2  * project: org.matsim.*
3  * VisumMatrixReader.java
4  * *
5  * *********************************************************************** *
6  * *
7  * copyright : (C) 2007 by the members listed in the COPYING, *
8  * LICENSE and WARRANTY file. *
9  * email : info at matsim dot org *
10  * *
11  * *********************************************************************** *
12  * *
13  * This program is free software; you can redistribute it and/or modify *
14  * it under the terms of the GNU General Public License as published by *
15  * the Free Software Foundation; either version 2 of the License, or *
16  * (at your option) any later version. *
17  * See also COPYING, LICENSE and WARRANTY file *
18  * *
19  * *********************************************************************** */
20 
21 package org.matsim.visum;
22 
23 import java.io.BufferedReader;
24 import java.io.IOException;
25 
26 import org.apache.logging.log4j.LogManager;
27 import org.apache.logging.log4j.Logger;
28 import org.matsim.core.utils.io.IOUtils;
29 import org.matsim.matrices.Matrix;
30 
34 public class VisumMatrixReader {
35 
36  private Matrix matrix = null;
37 
38  /*package*/ static final Logger log = LogManager.getLogger(VisumMatrixReader.class);
39 
40  public VisumMatrixReader(final Matrix matrix) {
41  this.matrix = matrix;
42  }
43 
44  public Matrix readFile(final String filename) {
45  BufferedReader infile = null;
46  try {
47  infile = IOUtils.getBufferedReader(filename);
48 
49  this.matrix.setDesc(filename);
50 
51  infile.mark(1024);
52  String header = infile.readLine();
53  infile.reset();
54 
55  if (header != null) {
56  if (header.equals("$VN;Y5")) {
57  new DenseMatrixReader(this.matrix).read(infile);
58  } else if (header.startsWith("$O")) {
59  new SparseMatrixReader(this.matrix).read(infile);
60  } else {
61  throw new RuntimeException("Visum file format '" + header +"' is not supported.");
62  }
63  } else {
64  throw new RuntimeException("header is missing");
65  }
66 
67  } catch (IOException e) {
68  e.printStackTrace();
69  return null;
70  } finally {
71  if (infile != null) {
72  try { infile.close(); }
73  catch (IOException e) { log.warn("Could not close input-stream.", e); }
74  }
75  }
76 
77  return matrix;
78  }
79 
80  private static class DenseMatrixReader {
81  /* I call the format, where the matrix is stored as a table in the file,
82  * a "dense matrix" format, as it is most effective for dense matrices. */
83  private final static int STATE_HEADER = 0;
84  private final static int STATE_ANZBEZIRKE = 1;
85  private final static int STATE_BEZIRKE = 2;
86  private final static int STATE_DATA = 3;
87  private final static int STATE_GARBAGE = 4;
88 
89  private int state = STATE_HEADER;
90  private String zoneNames[] = null;
91  private int zoneCounter = 0;
92  private int lineCounter = 0;
93  private int nofZones = 0;
94  private final Matrix matrix;
95 
96  public DenseMatrixReader(final Matrix matrix) {
97  this.matrix = matrix;
98  }
99 
100  public void read(final BufferedReader in) throws IOException {
101  String line = null;
102  while ( (line = in.readLine()) != null) {
103  this.lineCounter++;
104  if (!line.startsWith("*")) {
105  parseLine(line);
106  }
107  }
108  }
109 
110  private void parseLine(final String line) {
111 
112  if (this.state == STATE_DATA) {
113 
114  String[] data = line.split("\t");
115  if (data.length != this.nofZones) {
116  throw new RuntimeException("Expected " + this.nofZones + " data items, but found " + data.length +
117  " in line " + this.lineCounter + ".");
118  }
119  for (int i = 0; i < this.nofZones; i++) {
120  this.matrix.setEntry(this.zoneNames[this.zoneCounter], this.zoneNames[i], Double.parseDouble(data[i]));
121  }
122  this.zoneCounter++;
123  if (this.zoneCounter == this.nofZones) {
124  this.state = STATE_GARBAGE;
125  }
126 
127  } else if (this.state == STATE_HEADER) {
128 
129  // we ignore the header line
130  this.state = STATE_ANZBEZIRKE; // we expect as next the number of zones
131 
132  } else if (this.state == STATE_ANZBEZIRKE) {
133 
134  this.nofZones = Integer.parseInt(line);
135  this.state = STATE_BEZIRKE;
136 
137  } else if (this.state == STATE_BEZIRKE) {
138 
139  this.zoneNames = line.split("\t");
140  if (this.zoneNames.length != this.nofZones) {
141  throw new RuntimeException("Line " + this.lineCounter + ": " +
142  "The actual number of zones (" + this.zoneNames.length + ") does not " +
143  "correspond with the expected number of zones (" + this.nofZones + ")."
144  );
145  }
146  this.zoneCounter = 0;
147  this.state = STATE_DATA;
148 
149 // } else if (this.state == STATE_GARBAGE) {
150 // ignore the data
151  }
152  }
153 
154  }
155 
156  /*default*/ static class SparseMatrixReader {
157  /* I call the format, where each entry of the matrix is written on its
158  * own line together with a from- and to-cell-id, a "sparse matrix" format,
159  * as it is most effective for storing sparse matrices. */
160  private final static int STATE_HEADER = 0;
161  private final static int STATE_VERKEHRSMITTEL = 1;
162  private final static int STATE_TIME = 2;
163  private final static int STATE_FAKTOR = 3;
164  private final static int STATE_DATA = 4;
165 
166  private int state = STATE_HEADER;
167  private int lineCounter = 0;
168  private final Matrix matrix;
169 
170  public SparseMatrixReader(final Matrix matrix) {
171  this.matrix = matrix;
172  }
173 
174  public void read(final BufferedReader in) throws IOException {
175  String line = null;
176  while ( (line = in.readLine()) != null) {
177  this.lineCounter++;
178  if (!line.startsWith("*")) {
179  parseLine(line);
180  }
181  }
182  }
183 
184  private void parseLine(final String line) {
185 
186  if (this.state == STATE_DATA) {
187 
188  String[] data = line.trim().split("\\s+");
189  if (data.length != 3) {
190  throw new RuntimeException("Expected 3 tokens, but found " + data.length + " in line " + this.lineCounter + "."
191  );
192  }
193 
194  String from = data[0];
195  String to = data[1];
196 
197  /*
198  * There is no intrazonal traffic in VISUM.
199  * However, when there comes a matrix entry from VISUMĀ 
200  * for a tuple of one and the same zone, store NaN instead of the value.
201  * This indicates that the value has to be computed otherwise in MATSim.
202  */
203  double value = Double.NaN;
204  if (!from.equals(to)) {
205  value = Double.parseDouble(data[2]);
206  }
207  this.matrix.createAndAddEntry(from, to, value);
208 
209  } else if (this.state == STATE_HEADER) {
210 
211  // we ignore the header line
212  this.state = STATE_VERKEHRSMITTEL; // we expect as next the Verkehrsmittel-Nr
213 
214  } else if (this.state == STATE_VERKEHRSMITTEL) {
215 
216  // ignore verkehrsmittel
217  this.state = STATE_TIME;
218 
219  } else if (this.state == STATE_TIME) {
220 
221  // ignore time
222  this.state = STATE_FAKTOR;
223 
224  } else if (this.state == STATE_FAKTOR) {
225 
226  // ignore faktor
227  this.state = STATE_DATA;
228 
229  } else {
230  throw new RuntimeException("unknown internal state: " + this.state);
231  }
232  }
233 
234  }
235 
236 }
final Entry createAndAddEntry(final String fromLocId, final String toLocId, final double value)
Definition: Matrix.java:65
static BufferedReader getBufferedReader(URL url, Charset charset)
Definition: IOUtils.java:321
Matrix readFile(final String filename)
final Entry setEntry(final String fromLocId, final String toLocId, final double value)
Definition: Matrix.java:99
final void setDesc(final String desc)
Definition: Matrix.java:108